/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.repository.adaptoritem;

import com.inspur.edp.cef.api.CefRtBeanUtil;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.authority.AuthorityInfo;
import com.inspur.edp.cef.api.authority.AuthorityInfoType;
import com.inspur.edp.cef.api.repository.*;
import com.inspur.edp.cef.api.repository.readerWriter.ICefReader;
import com.inspur.edp.cef.entity.UQConstraintMediate;
import com.inspur.edp.cef.entity.changeset.ModifyChangeDetail;
import com.inspur.edp.cef.entity.changeset.ValueObjModifyChangeDetail;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.condition.ExpressCompareType;
import com.inspur.edp.cef.entity.condition.ExpressRelationType;
import com.inspur.edp.cef.entity.condition.FieldsFilter;
import com.inspur.edp.cef.entity.condition.FilterCondition;
import com.inspur.edp.cef.entity.condition.RetrieveFilter;
import com.inspur.edp.cef.entity.condition.SortCondition;
import com.inspur.edp.cef.entity.dependenceTemp.DataValidator;
import com.inspur.edp.cef.entity.dependenceTemp.Pagination;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.entity.entity.IChildEntityData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IMultiLanguageData;
import com.inspur.edp.cef.entity.i18n.MultiLanguageInfo;
import com.inspur.edp.cef.entity.repository.DataSaveParameter;
import com.inspur.edp.cef.repository.adaptor.AdapterUQChecker;
import com.inspur.edp.cef.repository.adaptor.AdaptorRetrieveParam;
import com.inspur.edp.cef.repository.adaptor.EntityRelationalAdaptor;
import com.inspur.edp.cef.repository.adaptor.KeyWordsManager;
import com.inspur.edp.cef.repository.adaptor.MultiLangColumnInfo;
import com.inspur.edp.cef.repository.adaptoritem.dbprocessor.DbProcessor;
import com.inspur.edp.cef.repository.adaptoritem.sqlsnippetprocessor.SqlSnippetProcessor;
import com.inspur.edp.cef.repository.assembler.AbstractDataAdapterExtendInfo;
import com.inspur.edp.cef.repository.assembler.AssoCondition;
import com.inspur.edp.cef.repository.assembler.AssociationInfo;
import com.inspur.edp.cef.repository.dac.DacSaveContext;
import com.inspur.edp.cef.repository.dac.EntityDac;
import com.inspur.edp.cef.repository.dbcolumninfo.ComplexUdtRefColumnInfo;
import com.inspur.edp.cef.repository.dbcolumninfo.DbColumnInfo;
import com.inspur.edp.cef.repository.dbcolumninfo.DbColumnInfoCollection;
import com.inspur.edp.cef.repository.exception.CefRepositoryException;
import com.inspur.edp.cef.repository.extend.RepoExtendManager;
import com.inspur.edp.cef.repository.readerwriter.CefDataReader;
import com.inspur.edp.cef.repository.repo.BaseRootRepository;
import com.inspur.edp.cef.repository.utils.DatabaseUtil;
import com.inspur.edp.cef.repository.utils.FilterUtil;
import com.inspur.edp.cef.repository.utils.RepositoryUtil;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.ComplexUdtPropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.DataTypePropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.RefDataTypePropertyInfo;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.UdtPropertyInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefEntityResInfoImpl;
import com.inspur.edp.cef.spi.jsonser.base.StringUtils;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.dataaccess.DbType;
import io.iec.edp.caf.commons.exception.CAFRuntimeException;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.databaseobject.api.service.IDatabaseObjectRtService;
import io.iec.edp.caf.i18n.framework.api.language.EcpLanguage;
import io.iec.edp.caf.runtime.config.CefBeanUtil;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.Transactional;
import lombok.var;

public abstract class EntityRelationalReposAdaptor extends EntityRelationalAdaptor {

    private  CefEntityResInfoImpl entityResInfo;
    protected EntityManager entityManager;
    //    @PersistenceContext()
    private DbProcessor dbProcessor;
    private SqlSnippetProcessor sqlSnippetProcessor;
    private EntityDac entityDac;
    private List<AdaptorItem> adaptorItemList;
    private static String authoritySql = " JOIN (%1$s) %2$s ON %3$s = %4$s";
    private static String authorityTableAlias = "authorityTable";
    private static String GetDataWithParentJoinSql = "select %1$s from %2$s %3$s %4$s";
    private DbColumnInfoCollection extendContainColumns;
    private DbColumnInfoCollection tempContainColumns = new DbColumnInfoCollection();
    private List<AssociationInfo> extendAssociations;
    //是关联进入，还是直接进入 并发下构造的关联columninfo 别名可能不正确
    private boolean isInitColumn = true;
    //    private java.util.ArrayList<AssociationInfo> associationInfos;
    private Boolean hasMultiLangCol;
    private String queryTableName;
    // endregion
    private HashMap<String, Integer> filteredPropDbIndexMapping = null;
    private DbColumnInfoCollection multiLanguageColumnInfos;
    private Map<String, MultiLangColumnInfo> multiLanguageAlias;//<Key:国际化后缀别名 Name_CHS,Value:字段标签Name>
    private boolean isMultiData = false;
    private Map<Integer, String> insertMultiIndexMap = new HashMap<>();
    private String tableAlias;
    private String originTableAlias = "";
    //过滤字段查询
    private FieldsFilter fieldsFilter;
    protected EntityRelationalReposAdaptor(boolean init, EntityDac entityDac) {
        super(init);
        this.entityDac = entityDac;
        entityManager = CefBeanUtil.getEntityManager();
    }

    public EntityRelationalReposAdaptor(boolean init,EntityDac entityDac, CefEntityResInfoImpl entityResInfo,String tableAlias)
    {
        this(init,entityDac);
        this.entityResInfo = entityResInfo;
        this.tableAlias = tableAlias;
        this.originTableAlias = tableAlias;
        if(this.entityResInfo.getSqlSnippetCache()==null) {
            entityResInfo.setSqlSnippetCache(new SqlSnippetCache());
        }
        addAdaptorItem(new BaseAdaptorItem(this,1));
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public DbProcessor getDbProcessor() {
        return  getSqlSnippetProcessor().getDbProcessor();
    }

    private SqlSnippetProcessor getSqlSnippetProcessor() {
        return getSqlSnippetCache().getSqlSnippetProcessor(entityDac.getGspDbtype().toString(),this);
    }

    protected abstract String getDboID();

    protected String getNodeCode() {
        return entityDac.getNodeCode();
    }

    //region VersionControl
    protected String getVersionControlPropName() {
        if(entityResInfo==null)
            return "";
        return entityResInfo.getVersionControlPropertyName();
    }

    public HashMap<String, Date> getVersionControlValues(List<String> dataIds) {
        if (getVersionControlPropName() == null || getVersionControlPropName().equals("")) {
            return new HashMap<>();
        }
        String sql = String.format(getGetDataByIdsSql(), getContainColumns().getPrimaryKey().getDbColumnName() + "," + getVersionControlPropName(), getTableName(), "%1$s");
        sql = formatFiscalAndMultiLang(sql);
        int batchCount = 5000;
        HashMap<String, Date> dic = new HashMap<>();
        if(dataIds != null && dataIds.size() > batchCount){
            int times = dataIds.size()%batchCount == 0 ? dataIds.size()/batchCount : dataIds.size()/batchCount + 1;
            for(int i=1 ;i<= times;i++){
                int endIndex = i == times ? dataIds.size() : batchCount*i;
                List<String> tempList = dataIds.subList(batchCount* (i-1), endIndex);
                String sqlformat = String.format(sql, getInFilter(tempList));
                HashMap<String, Date> tempDic = convertVersionControlValues(sqlformat, tempList, null);
                dic.putAll(tempDic);
            }
        }
        else {
            String sqlformat = String.format(sql, getInFilter(dataIds));
            HashMap<String, Date> tempDic = convertVersionControlValues(sqlformat, dataIds, null);
            dic.putAll(tempDic);
        }
        return dic;
    }

    public Date getVersionControlValue(String dataId) {
        if (getVersionControlPropName() == null || getVersionControlPropName().equals("")) {
            return new Date(0);
        }
        String sql = String.format(getGetDataByIdSql(), getVersionControlPropName(), getTableName(), "?0 ");
        try {
            List<DbParameter> list = new ArrayList<DbParameter>();
            list.add(buildParam("ID", getContainColumns().getPrimaryKey().getColumnType(), dataId));
            Date value = convertVersionControlValue(sql, list);
            return value;
        } catch (Exception ex) {
            throw new CefRepositoryException("cef_exception.properties", "Gsp_Cef_Retrieve_0001", new String[]{ex.getMessage()}, ex, ExceptionLevel.Info, true);
        }
    }

    private HashMap<String, Date>  convertVersionControlValues(String sql, List<String> dataIds, List<DbParameter> parameters) {
        Query query = buildQueryManager(sql, parameters);
        HashMap<String, Date> dic = new HashMap<String, Date>();
        List<Object[]> resultSet = query.getResultList();
        List<Date> results = new ArrayList<Date>();
        for(String dataId: dataIds){
            List<Object[]> objs = resultSet.stream().filter(item->item[0].equals(dataId)).collect(Collectors.toList());
            if(objs != null && objs.size() >0){
                var instance = new Date(0);
                if (objs.get(0)[1] != null) {
                    instance = (Date) objs.get(0)[1];
                }
                dic.put(dataId, instance);
            }
        }
        return dic;
    }

    private Date convertVersionControlValue(String sql, List<DbParameter> parameters) {
        Query query = buildQueryManager(sql, parameters);
        List resultSet = query.getResultList();
        if (resultSet == null || resultSet.isEmpty()) {
            throw new CefRepositoryException("数据不存在或已被删除");
        } else {
            Object result = resultSet.get(0);
            return result == null ? new Date(0) : (Date) result;
        }
    }
    //endregion
    // region Query
    @Override
    public List<IEntityData> query(EntityFilter filter, ArrayList<AuthorityInfo> authorities) {
        if(filter == null){
            throw new CefRepositoryException("查询过滤条件不能为空");
        }
        buildLogicDeleteCondition(filter);
        if (filter.getIsUsePagination()) {
            return queryWithPagination(filter, authorities);
        } else {
            return queryWithoutPagination(filter, authorities);
        }
    }

    @Override
    public void setDataAdapterExtendInfos(ArrayList<AbstractDataAdapterExtendInfo> infos) {
        super.setDataAdapterExtendInfos(infos);
        extendContainColumns = new DbColumnInfoCollection();
        for (AbstractDataAdapterExtendInfo info : infos) {
            if (info.getDbColumnInfos() == null)
                continue;
            extendContainColumns.addRange(info.getDbColumnInfos());
        }
        for (AbstractDataAdapterExtendInfo info : infos) {
            if (info.getAssociationInfos() == null)
                continue;
            if (extendAssociations == null)
                extendAssociations = new ArrayList<>();
            extendAssociations.addAll(info.getAssociationInfos());
        }
    }

    //region TODO 应该不需要生成
    protected  boolean hasPropColumnMappping()
    {return getSqlSnippetCache().getPropIndexMappingDict()!=null;}

    protected  HashMap<String, Integer> getPropertyColumnMapping()
    {return getSqlSnippetCache().getPropIndexMappingDict();}

    protected void setPropertyColumnMapping(HashMap<String, Integer> mapping)
    {getSqlSnippetCache().setPropIndexMappingDict(mapping);}

    public HashMap<String, String> getAssosPropDBMapping(String propName) {
        return ((BaseAdaptorItem)getBaseAdaptorItem()).getAssosPropDBMapping(propName);
    }

    private HashMap<String, Integer> innerGetPropertyColumnMapping() {
        HashMap<String, Integer> mapping = getPropertyColumnMapping();
        return mapping;
    }

    private List<IEntityData> queryWithoutPagination(EntityFilter filter, ArrayList<AuthorityInfo> authorities) {
        String tableName = getQueryTableNameWithAuthority(authorities, filter);
        StringBuilder sql = new StringBuilder();
        sql.append(String.format("SELECT %1$s FROM %2$s ", getQueryFields(filter), tableName));
        ArrayList<DbParameter> parameter = new ArrayList<DbParameter>();
        String condition = buildWhereCondition(getDB(), filter.getFilterConditions(), parameter, authorities);
        String sort = buildOrderByCondition(filter.getSortConditions());
        if (condition != null && condition.length() > 0) {
            sql.append(String.format(" WHERE %1$s", condition));
        }
        if (sort != null && sort.length() > 0) {
            sql.append(String.format(" Order By %1$s", sort));
        }
        try {
            return getDatas(RepositoryUtil.FormatMuliLangBySpecLang(sql.toString(), filter.getEnableLanguage()), parameter);
        } catch (Exception e) {
            throw new CefRepositoryException("查询失败", e);
        }
    }

    private List<IEntityData> queryWithPagination(EntityFilter filter, ArrayList<AuthorityInfo> authorities) {

        String tableName = getQueryTableNameWithAuthority(authorities, filter);
        ArrayList<DbParameter> parameter = new ArrayList<DbParameter>();
        String condition = buildWhereCondition(getDB(), filter.getFilterConditions(), parameter, authorities);
        String sort = buildOrderByCondition(filter.getSortConditions());
        Pagination pagination = filter.getPagination();
        try {
            RefObject<Pagination> tempRef_pagination = new RefObject<Pagination>(pagination);
            List<IEntityData> tempVar = DatabaseUtil.getPaginationData(tableName, getTableName(), RepositoryUtil.FormatMuliLangBySpecLang((getQueryFields(filter)), filter.getEnableLanguage()),
                    getWrappedTableAlias().concat(".").concat(getContainColumns().getPrimaryKey().getDbColumnName()),
                    condition,
                    sort,
                    parameter,
                    tempRef_pagination,
                    this, isTableView());
            pagination = tempRef_pagination.argvalue;
            return tempVar;
        } catch (Exception e) {
            throw new CefRepositoryException("执行分页取数失败", e);
        }
    }

    private String getQueryFields(EntityFilter filter) {
        StringBuilder sb = new StringBuilder();
        HashMap<String, Integer> mapping = new HashMap<>();

        for (int i = 0; i < adaptorItemList.size(); i++) {
            if (i > 0) {
                sb.append(",").append(adaptorItemList.get(i).getQueryFields(filter, mapping));
            } else {
                sb.append(adaptorItemList.get(i).getQueryFields(filter, mapping));
            }
        }
        if (extendContainColumns != null && extendContainColumns.getCount() > 0) {
            //运行时定制修改Mappingying影响到了缓存
            HashMap<String, Integer> tempMapping = new HashMap<>();
            //todo 这个地方直接赋值 返回到调用处不好使。。后续研究原因
            for (Map.Entry<String, Integer> item : mapping.entrySet()) {
                tempMapping.put(item.getKey(), item.getValue());
            }
            RepoExtendManager repoExtendManager = new RepoExtendManager();
            String queryFields = repoExtendManager.buildQueryFields(getTableAlias(), extendContainColumns, filter, tempMapping);
            if (!StringUtils.isNullOrEmpty(queryFields)) {
                sb.append(",").append(queryFields);
            }
            filteredPropDbIndexMapping = tempMapping;
        } else {
            filteredPropDbIndexMapping = mapping;
            if (filteredPropDbIndexMapping == null || filteredPropDbIndexMapping.size() == 0) {//换成过滤字段的情况
                filteredPropDbIndexMapping = getBaseAdaptorItem().getSqlCache().getQueryMappingMap().get(getGspDbType().toString());
            }
        }
        return sb.toString();
    }

    private String getQueryFieldsWithOutCache(EntityFilter filter) {
        StringBuilder sb = new StringBuilder();
        HashMap<String, Integer> mapping = new HashMap<>();

        for (int i = 0; i < adaptorItemList.size(); i++) {
            if (i > 0) {
                sb.append(",").append(adaptorItemList.get(i).getQueryFieldsWithOutCache(filter, mapping));
            } else {
                sb.append(adaptorItemList.get(i).getQueryFieldsWithOutCache(filter, mapping));
            }
        }
        if (extendContainColumns != null && extendContainColumns.getCount() > 0) {
            String columns = RepoExtendManager.buildQueryFields(getTableAlias(), extendContainColumns, filter, mapping);
            if (columns.length() > 0) {
                sb.append(",").append(columns);
            }
        }
        filteredPropDbIndexMapping = mapping;
        return sb.toString();
    }

    private String getQueryFields(AdaptorRetrieveParam adaptorRetrieveParam) {
        EntityFilter filter = adaptorRetrieveParam.getEntityfilter(getNodeCode());
        // 构造非多语列列名
        String fields = getQueryFields(filter);
        if (adaptorRetrieveParam == null || !adaptorRetrieveParam.isEnableMultiLanguage()) {
            return fields;
        }
        String multiLangFields = buildQueryColumns_MultiLanguage(filter);
        if (multiLangFields.length() > 0 && fields.length() > 0) {
            fields = fields.concat("," + multiLangFields);
        }
        return fields;
    }

    private String getQueryFieldsWithOutCache(AdaptorRetrieveParam adaptorRetrieveParam) {
        EntityFilter filter = adaptorRetrieveParam.getEntityfilter(getNodeCode());
        // 构造非多语列列名
        String fields = getQueryFieldsWithOutCache(filter);
        if (adaptorRetrieveParam == null || !adaptorRetrieveParam.isEnableMultiLanguage()) {
            return fields;
        }
        String multiLangFields = buildQueryColumns_MultiLanguage(filter);
        if (multiLangFields.length() > 0 && fields.length() > 0) {
            fields = fields.concat("," + multiLangFields);
        }
        return fields;
    }

    private String getQueryTableNameWithAuthority(ArrayList<AuthorityInfo> authorities, EntityFilter filter) {
        String tempQueryTableName = "";
        if (filter != null && filter.getFieldsFilter() != null && filter.getFieldsFilter().isUseFieldsCondition()) {
            this.fieldsFilter = filter.getFieldsFilter();
        }
        initQueryTableName();
        tempQueryTableName = queryTableName;
        String authority = getAuthoritySql(authorities);
        return tempQueryTableName + authority;
    }

//    private String getQueryTableNameByFields(EntityFilter filter) {
//        ArrayList<AssociationInfo> associationInfos = new ArrayList<>();
//        for (AssociationInfo associationInfo : getAssociationInfos()) {
//            if (filter.getFieldsFilter().getFilterFields().contains(associationInfo.getSourceColumn())) {
//                associationInfos.add(associationInfo);
//            }
//        }
//        return getTableNamesWithAssociationInfo(associationInfos, null);
//    }

    private String getAuthoritySql(ArrayList<AuthorityInfo> authorities) {
        if (authorities == null || authorities.size() < 1) {
            return "";
        }
        StringBuilder authorityBuilder = new StringBuilder();
        for (int i = 1; i < authorities.size() + 1; i++) {
            AuthorityInfo info = authorities.get(i - 1);
            if(info.getAuthType() != AuthorityInfoType.Join) {
                continue;
            }
            String aliasName = authorityTableAlias + i;
            String fieldName = trans2DbColumnWithAlias(info.getFieldName());
            String sourceFieldName = aliasName + "." + info.getSourceFieldName();

            authorityBuilder.append(String.format(authoritySql, info.getAuthoritySql(), aliasName, fieldName, sourceFieldName));
        }

        return authorityBuilder.toString();
    }


    // endregion

    // region
    // buildWhereCondition, 目前权限过滤条件要求parameter必须为空
    private String buildWhereCondition(Connection db, ArrayList<FilterCondition> filter,
        ArrayList<DbParameter> parameter, List<AuthorityInfo> authorities) {
        //DynamicParameters
        String authCondition = getAuthFilterCondition(db, parameter, authorities);

        String beCondition = getDefaultCondition(db, parameter);

        String externalCondition = parseFilterCondition(getDB(), filter, parameter,
                parameter.size(), false);

        String tenantCondition = getTenantCondition();

        String condition = String.format("%1$s%2$s%3$s%4$s", authCondition, beCondition, externalCondition, tenantCondition);
        if (condition.startsWith(" AND ")) {
            condition = condition.substring(4);
        }

        if (condition == null || condition.length() == 0) {
            return condition;
        }
        return formatMultiLang(condition);
    }

    private void buildLogicDeleteCondition(EntityFilter entityFilter) {
        if (!getLogicDeleteInfo().isEnableLogicDelete())
            return;
        if (entityFilter == null)
            entityFilter = new EntityFilter();
        if (entityFilter.getFilterConditions() == null) {
            ArrayList<FilterCondition> filterConditions = new ArrayList<>();
            entityFilter.setFilterConditions(filterConditions);
        }
        if (entityFilter.getFilterConditions().size() > 0) {//修改最后一个的relation符号
            entityFilter.getFilterConditions().get(0).setLbracket(entityFilter.getFilterConditions().get(0).getLbracket() + "(");
            entityFilter.getFilterConditions().get(entityFilter.getFilterConditions().size() - 1).setRbracket(entityFilter.getFilterConditions().get(entityFilter.getFilterConditions().size() - 1).getRbracket() + ")");
            entityFilter.getFilterConditions().get(entityFilter.getFilterConditions().size() - 1).setRelation(ExpressRelationType.And);
        }
        FilterCondition filterCondition = new FilterCondition();
        filterCondition.setValue("1");
        filterCondition.setFilterField(getLogicDeleteInfo().getLabelId());
        filterCondition.setCompare(ExpressCompareType.NotEqual);
        entityFilter.getFilterConditions().add(filterCondition);
    }

    private String getDefaultCondition(Connection db, ArrayList<DbParameter> parameter) {
        ArrayList<FilterCondition> filterConditions = getDefaultFilterCondition();
        if (filterConditions == null || filterConditions.size() < 1) {
            return "";
        }
        StringBuilder conditionBuilder = new StringBuilder("(");
        int paramNum = parameter.size();
        for (FilterCondition filterItem : filterConditions) {
            String columnName = "";
            if (filterItem.getFilterField() != null && filterItem.getFilterField().isEmpty() == false)
                columnName = trans2DbColumnWithAlias(filterItem.getFilterField());

            GspDbDataType dataType = getDataType(filterItem.getFilterField());
            RefObject<Integer> tempRef_paramNum = new RefObject<Integer>(paramNum);
            conditionBuilder.append(FilterUtil.parseFilterCondition(filterItem, columnName, parameter, db, dataType, tempRef_paramNum, getTypeTransProcesser(filterItem.getFilterField())));
            paramNum = tempRef_paramNum.argvalue;
        }

        conditionBuilder.append(")");

        return conditionBuilder.toString();
    }

    private int buildFieldCondition(Connection db, List<DbParameter> parameters, int paramNum, boolean ignoreAlias, StringBuilder conditionBuilder, FilterCondition filterItem) {
        String columnName = "";
        if (filterItem.getFilterField() != null && filterItem.getFilterField().isEmpty() == false)
            columnName = trans2DbColumnWithAlias(filterItem.getFilterField(), ignoreAlias);

        GspDbDataType dataType = getDataType(filterItem.getFilterField());
        RefObject<Integer> tempRef_paramNum = new RefObject<Integer>(paramNum);
        conditionBuilder.append(FilterUtil.parseFilterCondition(filterItem, columnName, parameters, db, dataType, tempRef_paramNum, getTypeTransProcesser(filterItem.getFilterField())));
        paramNum = tempRef_paramNum.argvalue;
        return paramNum;
    }

    @Override
    public final EntityDac getEntityDac() {
        return this.entityDac;
    }

    private String getTenantCondition() {
        return "";
    }

    private String buildOrderByCondition(ArrayList<SortCondition> orderByConditions) {
        ArrayList<SortCondition> defaultSortCondition = getDefaultSortCondition();
        String defaultSort = buildDefaultOrderByCondition(defaultSortCondition);
        StringBuilder orderByBuilder = new StringBuilder(defaultSort);
        if (orderByConditions != null && orderByConditions.size() > 0) {
            ArrayList<SortCondition> sortConditions = transSortCondition(orderByConditions);
            for (SortCondition orderByItem : sortConditions) {
                if (orderByBuilder.toString() != null && !"".equals(orderByBuilder.toString())) {
                    orderByBuilder.append(", ");
                }
                String filedName = trans2DbColumnWithAlias(orderByItem.getSortField());
                orderByBuilder.append(orderByItem.trans2Sql(filedName));
            }
        }

        if (orderByBuilder.toString() == null || orderByBuilder.toString().length() == 0) {
            return getWrappedTableAlias() + "." + getContainColumns().getPrimaryKey().getDbColumnName() + " ASC";
        }
        return formatMultiLang(orderByBuilder.toString());
    }

    private ArrayList<SortCondition> transSortCondition(ArrayList<SortCondition> orderByConditions) {
        HashMap<String, SortCondition> sortConditions = new HashMap<String, SortCondition>();
        ArrayList<SortCondition> sorts = new ArrayList<SortCondition>();
        for (SortCondition sortCondition : orderByConditions) {
            if (!sortConditions.containsKey(sortCondition.getSortField().toLowerCase())) {
                sortConditions.put(sortCondition.getSortField().toLowerCase(), sortCondition);
                sorts.add(sortCondition);
            }
        }

        return sorts;
    }

    private String buildDefaultOrderByCondition(ArrayList<SortCondition> sortConditions) {
        StringBuilder orderByBuilder = new StringBuilder();
        if (sortConditions != null && sortConditions.size() > 0) {
            for (SortCondition orderByItem : sortConditions) {
                if (orderByBuilder.toString() != null && !orderByBuilder.toString().equals("")) {
                    orderByBuilder.append(", ");
                }
                String filedName = trans2DbColumnWithAlias(orderByItem.getSortField());
                orderByBuilder.append(orderByItem.trans2Sql(filedName));
            }
        }
        return String.valueOf(orderByBuilder);
    }

    public String getInIDsFilter(List<String> dataIds) {
        return String.format(" where %1$s.%2$s IN %3$s", getWrappedTableAlias(), getContainColumns().getPrimaryKey().getDbColumnName(), FilterUtil.buildInCondition(dataIds.toArray(new String[]{}), false, getWrappedTableAlias() + "." + getContainColumns().getPrimaryKey().getDbColumnName()));
    }

    public String getInFilter(List<String> dataIds) {
        return FilterUtil.buildInCondition(dataIds.toArray(new String[]{}), false, getWrappedTableAlias() + "." + getContainColumns().getPrimaryKey().getDbColumnName());
    }

    public String getIDFilter() {
        return String.format(" where %1$s.%2$s=", getWrappedTableAlias(), getContainColumns().getPrimaryKey().getDbColumnName()) + "?0";
    }

    public final List<IChildEntityData> getDataWithParentJoinIds(String joinInfo, String condition
            , ArrayList<SortCondition> orderByCondition, ArrayList<String> tableAlias, List<DbParameter> dbPars) {
        return this.getDataWithParentJoinIds(joinInfo, condition, orderByCondition, tableAlias, dbPars, null);
    }

    public final List<IChildEntityData> getDataWithParentJoinIds(String joinInfo, List<String> conditions
            , ArrayList<SortCondition> orderByCondition, ArrayList<String> tableAlias, List<DbParameter> dbPars, AdaptorRetrieveParam adaptorRetrieveParam) {
        EntityFilter filter = adaptorRetrieveParam != null ? adaptorRetrieveParam.getEntityfilter(getNodeCode()) : null;
        if (filter != null && filter.getFieldsFilter() != null && filter.getFieldsFilter().isUseFieldsCondition()) {
            this.fieldsFilter = filter.getFieldsFilter();
        }
        initQueryTableNameWithParentAlias(tableAlias, adaptorRetrieveParam);
        List<IChildEntityData> childDatas = new ArrayList<IChildEntityData>();
        if(conditions != null && conditions.size() >0){
            for(String condition :conditions){
                List<DbParameter> tempdbPars = new ArrayList<>();
                if (getLogicDeleteInfo().isEnableLogicDelete()) {
                    if(dbPars != null && dbPars.size() > 0){
                        tempdbPars.addAll(dbPars);
                    }
                    tempdbPars.add(buildParam(getLogicDeleteInfo().getLabelId(), GspDbDataType.Char, "0"));
                    condition += " and " + getWrappedTableAlias() + "." + getLogicDeleteInfo().getLabelId() + " = ?" + (tempdbPars.size() - 1);
                }
                String sql = "";
                if(!StringUtils.isNullOrEmpty(joinInfo) && CAFContext.current.getDbType() == DbType.Oscar){
                    sql = String.format(GetDataWithParentJoinSql, getQueryFieldsWithOutCache(adaptorRetrieveParam), getTableName() + " " +joinInfo, joinTableName, condition);
                }
                else {
                    sql = String.format(GetDataWithParentJoinSql, getQueryFieldsWithOutCache(adaptorRetrieveParam), queryTableName, joinInfo, condition);
                }
                sql += buildRetrieveOrderBy(orderByCondition);
                RetrieveFilter retrieveFilter = adaptorRetrieveParam == null ? null : adaptorRetrieveParam.getRetrieveFilter();
                sql = formatFiscalAndMultiLang(sql, retrieveFilter);
                List<IEntityData> datas = getDatas(sql, tempdbPars, adaptorRetrieveParam);
                if (datas == null)
                    return null;
                for (IEntityData data : datas) {
                    childDatas.add((IChildEntityData) data);
                }
            }
        }

        return childDatas;
    }

    public final List<IChildEntityData> getDataWithParentJoinIds(String joinInfo, String condition
            , ArrayList<SortCondition> orderByCondition, ArrayList<String> tableAlias, List<DbParameter> dbPars, AdaptorRetrieveParam adaptorRetrieveParam) {
        EntityFilter filter = adaptorRetrieveParam != null ? adaptorRetrieveParam.getEntityfilter(getNodeCode()) : null;
        if (filter != null && filter.getFieldsFilter() != null && filter.getFieldsFilter().isUseFieldsCondition()) {
            this.fieldsFilter = filter.getFieldsFilter();
        }
        initQueryTableNameWithParentAlias(tableAlias, adaptorRetrieveParam);
        if (getLogicDeleteInfo().isEnableLogicDelete()) {
            if (dbPars == null)
                dbPars = new ArrayList<>();
            dbPars.add(buildParam(getLogicDeleteInfo().getLabelId(), GspDbDataType.Char, "0"));
            condition += " and " + getWrappedTableAlias() + "." + getLogicDeleteInfo().getLabelId() + " = ?" + (dbPars.size() - 1);
        }

        String sql = "";
        if(!StringUtils.isNullOrEmpty(joinInfo) && CAFContext.current.getDbType() == DbType.Oscar){
            sql = String.format(GetDataWithParentJoinSql, getQueryFieldsWithOutCache(adaptorRetrieveParam), getTableName() + " " + joinInfo, joinTableName, condition);
        }
        else {
            sql = String.format(GetDataWithParentJoinSql, getQueryFieldsWithOutCache(adaptorRetrieveParam), queryTableName, joinInfo, condition);
        }
        sql += buildRetrieveOrderBy(orderByCondition);
        RetrieveFilter retrieveFilter = adaptorRetrieveParam == null ? null : adaptorRetrieveParam.getRetrieveFilter();
        sql = formatFiscalAndMultiLang(sql, retrieveFilter);
        List<IEntityData> datas = getDatas(sql, dbPars, adaptorRetrieveParam);
        if (datas == null)
            return null;
        List<IChildEntityData> childDatas = new ArrayList<IChildEntityData>();
        for (IEntityData data : datas) {
            childDatas.add((IChildEntityData) data);
        }
        return childDatas;
    }

    private String buildRetrieveOrderBy(ArrayList<SortCondition> orderBys) {
        if (orderBys == null || orderBys.size() < 1) {
            return "";
        }
        return " ORDER BY " + buildDefaultOrderByCondition(orderBys);
    }

    public GspDbType getGspDbType() {
        return entityDac.getGspDbtype();
    }

    public void addAdaptorItem(AdaptorItem adaptorItem) {
        if (adaptorItemList == null)
            adaptorItemList = new ArrayList<AdaptorItem>();
        adaptorItemList.add(adaptorItem);
    }

    public  AdaptorItem getBaseAdaptorItem()
    {
        return adaptorItemList.get(0);
    }

    public final DbColumnInfoCollection getContainColumns(boolean isInitColumn) {
        if (isInitColumn) {
            return getContainColumns();
        } else {
            return tempContainColumns;
        }
    }

    public final DbColumnInfoCollection getContainColumns() {
        return getBaseAdaptorItem().getContainColumns();
    }

    public AdaptorItem getAdaptorItem(String columnName) {
        for (AdaptorItem item : adaptorItemList) {
            if (item.getContainColumns() != null && item.getContainColumns().getCount() > 0) {
                if (item.getContainColumns().contains(columnName))
                    return item;
            }
        }
        return adaptorItemList.get(0);
    }

    public DbColumnInfoCollection getContainColumns(String columnName) {
        DbColumnInfoCollection containedColumns = new DbColumnInfoCollection();
        for (AdaptorItem item : adaptorItemList) {
            if (item.getContainColumns() != null && item.getContainColumns().getCount() > 0) {
                if (item.getContainColumns().contains(columnName))
                    containedColumns.addRange(item.getContainColumns());
            }
        }
        return containedColumns;
    }

    /**
     *    看着像是不起作用，因为执行的时候，adaptoerItemList没有内容
     */
    protected void initColumns() {
        if (adaptorItemList != null && !adaptorItemList.isEmpty()) {
            adaptorItemList.forEach(a -> a.initColumns());
        }
    }

    @Override
    protected void initAssociations() {
        if (adaptorItemList != null && !adaptorItemList.isEmpty()) {
            adaptorItemList.forEach(a -> a.initAssociations());
        }
    }

    @Override
    protected java.util.ArrayList<AssociationInfo> getAssociationInfos() {
        ArrayList<AssociationInfo> associationInfos = new ArrayList<AssociationInfo>();
        for (AdaptorItem item : adaptorItemList) {
            if (item.getAssociationInfos() != null && item.getAssociationInfos().size() > 0) {
                associationInfos.addAll(item.getAssociationInfos());
            }
        }
        if (extendAssociations != null && extendAssociations.size() > 0) {
            associationInfos.addAll(extendAssociations);
        }
        return associationInfos;
    }

    @Override
    protected final AssociationInfo getAssociation(String propertyName) {
        for (AssociationInfo item : getAssociationInfos()) {
            if (propertyName.equals(item.getSourceColumn())) {
                return item;
            }
        }
        throw new CefRepositoryException("找不到" + propertyName + "属性对应的关联信息。");
    }

    protected ArrayList<FilterCondition> getDefaultFilterCondition(){
        return null;
    };

    protected  ArrayList<SortCondition> getDefaultSortCondition(){return null;}

    private void setParameters(PreparedStatement statement, List<DbParameter> parameters) throws SQLException {
        int index = 0;
        if (parameters == null || parameters.size() == 0)
            return;
        for (DbParameter parameter : parameters) {
            switch (parameter.getDataType()) {
                case VarChar:
                case Char:
                case NChar:
                case NVarChar:
                case Clob:
                case NClob:
                    statement.setString(index++, (String) parameter.getValue());
                    break;
                case Int:
                    statement.setInt(index++, (Integer) parameter.getValue());
                    break;
                case Decimal:
                    statement.setBigDecimal(index++, (BigDecimal) parameter.getValue());
                    break;
            }
        }
    }

    /**
     * 检索超过1W条数据,分拼执行合并结果
     * @param sql
     * @param dataIds
     * @return
     */
    public ArrayList<IEntityData> getDatasBatch(String sql, List<String> dataIds) {
        int batchCount = 5000;
        ArrayList<IEntityData> datas = new ArrayList<>();
        if(dataIds != null && dataIds.size() > batchCount){
            int times = dataIds.size()%batchCount == 0 ? dataIds.size()/batchCount : dataIds.size()/batchCount + 1;
            for(int i=1 ;i<= times;i++){
                int endIndex = i == times ? dataIds.size() : batchCount*i;
                List<String> tempList = dataIds.subList(batchCount* (i-1), endIndex);
                ArrayList<IEntityData> tempListData = getDatas(String.format(sql, getInFilter(tempList)), null);
                if(tempListData != null && tempListData.size() > 0){
                    datas.addAll(tempListData);
                }
            }
            return datas;
        }
        else {
            return this.getDatas(String.format(sql, getInFilter(dataIds)), null, new AdaptorRetrieveParam(null));
        }
    }

    public final ArrayList<IEntityData> getDatas(String sql, List<DbParameter> parameters) {
        return this.getDatas(sql, parameters, new AdaptorRetrieveParam(null));
    }

    private ArrayList<IEntityData> getDatas(String sql, List<DbParameter> parameters,
                                            AdaptorRetrieveParam param) {
        Query query = buildQueryManager(sql, parameters);
        List<Object[]> resultSet = null;
        try {
            resultSet = query.getResultList();
        } catch (Exception ex) {
            logger.error("tablealias:" + getTableAlias() + " 出错sql:" + sql);
            throw ex;
        }

        return innerGetDatas(resultSet, param);
    }

    public List<IEntityData> getDatasInPagination(List<Object[]> resultSet) {
        return innerGetDatas(resultSet);
    }

    public ArrayList<IEntityData> innerGetDatas(List<Object[]> resultSet) {
        return this.innerGetDatas(resultSet, null);
    }

    private ArrayList<IEntityData> innerGetDatas(List<Object[]> resultSet, AdaptorRetrieveParam param) {
        ArrayList<IEntityData> results = new ArrayList<IEntityData>();
        HashMap<String, Integer> mapping = filteredPropDbIndexMapping;
        for (Object[] result : resultSet) {
            IEntityData instance = createEntityInstance(new CefDataReader(result, mapping), param);
            results.add(instance);
        }
        return results;
    }

    @Override
    public ICefData createInstance(ICefReader reader) {
        ICefData data = entityDac.createInstance();
        for (AdaptorItem item : adaptorItemList) {
            item.setEntityValue(reader, (IEntityData) data);
        }
        return data;
    }

    private IEntityData createEntityInstance(ICefReader reader, AdaptorRetrieveParam pram) {
        ICefData tempVar = createInstance(reader);
        IEntityData data = (IEntityData) tempVar;
        for (AbstractDataAdapterExtendInfo extendInfo : getDataAdapterExtendInfos()) {
            extendInfo.setEntityPropertiesFromDal(reader, data);
        }
        // 处理多语列，赋值至ICefDataBase.MultiLanguageInfos
        if (pram != null && pram.isEnableMultiLanguage() && tempVar instanceof IMultiLanguageData) {
            IMultiLanguageData cefDataBase = (IMultiLanguageData) tempVar;
            Map<String, MultiLanguageInfo> resultInfos = cefDataBase.getMultiLanguageInfos();
            DbColumnInfoCollection columnInfos = this.getMultiLanguageColumnInfos();
            this.getMultiLanguageAlias().forEach((alias, multiLangColumnInfo) -> {
                if (reader.hasProperty(alias)) {
                    DbColumnInfo currentPropInfo = columnInfos
                            .getItem(multiLangColumnInfo.getColumnName());
                    if (currentPropInfo != null && currentPropInfo.getIsUdtElement()) {
                        // 多语控件不支持UDT
                        return;
                    }
                    String labelId =
                            multiLangColumnInfo.getColumnName() + MultiLanguageInfo.MULTILANGUAGETOKEN;
                    if (!resultInfos.containsKey(labelId)) {
                        resultInfos.put(labelId, new MultiLanguageInfo());
                    }
                    MultiLanguageInfo info = resultInfos.get(labelId);
                    info.setPropName(labelId);
                    // dm数据库获取数据需处理
                    Object currentAliasValue =
                            currentPropInfo.getColumnType().equals(GspDbDataType.NClob) ? getClobValue(reader
                                    .readValue(alias)) : reader.readValue(alias);
                    info.getPropValueMap()
                            .put(multiLangColumnInfo.getLanguageInfo().getCode(), currentAliasValue);
                }
            });
        }
        return (IEntityData) ((tempVar instanceof IEntityData) ? tempVar : null);
    }

    private IDatabaseObjectRtService getDboService() {
        return CefRtBeanUtil.getDboRtService();
    }

    public  String getPrimaryKey() {
        if (getSqlSnippetCache().getPrimaryKey() == null || ""
                .equals(getSqlSnippetCache().getPrimaryKey())) {
            for (DbColumnInfo dbColumnInfo : getContainColumns()) {
                if (dbColumnInfo.getIsPrimaryKey())
                    getSqlSnippetCache().setPrimaryKey(dbColumnInfo.getDbColumnName());
            }
        }
        return getSqlSnippetCache().getPrimaryKey();
    }

    public  String getTableAlias()
    {return tableAlias;}

    public  void setTableAlias(String value)
    {tableAlias=value;}

    //获取转换后的别名
    public final String getWrappedTableAlias() {
        return KeyWordsManager.getTableAlias(getTableAlias());
    }

    public  String getOriginTableAlias()
    {return this.originTableAlias;}

    public final String getWrappedOriginTableAlias() {
        if(StringUtils.isNullOrEmpty(getOriginTableAlias()))
            return "";
        return KeyWordsManager.getTableAlias(getOriginTableAlias());
    }
    public final String getWrappedTableAlias(boolean ignoreKeyWords) {
        return KeyWordsManager.getTableAlias(getTableAlias(), ignoreKeyWords);
    }

    //protected abstract String DefaultSort { get; }
    protected  String getConfigId()
    {return entityResInfo.getModelResInfo().getConfigId();}

    ///#region initQueryTableName
    private void initQueryTableName() {
        //if (!String.IsNullOrEmpty(queryTableName))
        //    return;
        ////跟之前一致，并且在当前实例上做缓存。
        //queryTableName = getTableNamesWithAssociationInfo(AssociationInfos, null);
        //buildQueryColumns();
        initQueryTableNameWithParentAlias(null);
    }
    // endregion

    // region MultiLanguageInfo

    private void initQueryTableNameWithParentAlias(ArrayList<String> alias) {
        this.initQueryTableNameWithParentAlias(alias, new AdaptorRetrieveParam(null));
    }

    private void initQueryTableNameWithParentAlias(ArrayList<String> alias, AdaptorRetrieveParam adaptorRetrieveParam) {
//        if (!(this.fieldsFilter != null && this.fieldsFilter.isUseFieldsCondition()) && queryTableName != null && queryTableName.length() > 0) {
//            return;
//        }
        //跟之前一致，并且在当前实例上做缓存。
        queryTableName = getTableNamesWithAssociationInfo(getAssociationInfos(), alias);
    }

    public final void buildQueryColumns() {
        buildQueryColumns(false, null, null);
    }

    private DbColumnInfoCollection getMultiLanguageColumnInfos() {
        //region TODO multiLanguageColumnInfos可以缓存起来，没必要每次都new
        this.multiLanguageColumnInfos = new DbColumnInfoCollection();
        //endregion
        for (DbColumnInfo col : getContainColumns()) {
            if (col.getIsMultiLang()) {
                this.multiLanguageColumnInfos.add(col);
                continue;
            }
        }
        return this.multiLanguageColumnInfos;
    }

    // endregion

    //
    private Map<String, MultiLangColumnInfo> getMultiLanguageAlias() {
        if (this.multiLanguageAlias != null) {
            return this.multiLanguageAlias;
        }
        this.multiLanguageAlias = new HashMap<>();
        List<EcpLanguage> currentEnableLanguages = RepositoryUtil.getCurrentEnabledLanguages();
        this.getMultiLanguageColumnInfos().forEach(
                columnInfo -> {
                    currentEnableLanguages.forEach(language -> {
                        MultiLangColumnInfo info = new MultiLangColumnInfo();
                        String alias = RepositoryUtil.FormatMuliLangColumnName(columnInfo.getColumnName(), language);
                        info.setColumnName(columnInfo.getColumnName());
                        info.setLanguageInfo(language);
                        this.multiLanguageAlias.put(alias, info);
                    });
                }
        );
        return this.multiLanguageAlias;
    }

    /**
     * 构建多语相关的列名 TableName.Name_CHS as Name_CHS
     *
     * @return
     */
    private String buildQueryColumns_MultiLanguage(EntityFilter filter) {
        DbColumnInfoCollection collection = this.getMultiLanguageColumnInfos();
        // 无多语字段
        if (collection.getCount() == 0) {
            return "";
        }

        StringBuilder columns = new StringBuilder();
        HashMap<String, Integer> currentIndexMap = filteredPropDbIndexMapping;//getPropertyColumnMapping();
        if (currentIndexMap == null) {
            throw new CefRepositoryException("当前PropertyColumnMapping为空");
        }

        List<EcpLanguage> currentEnableLanguages = RepositoryUtil.getCurrentEnabledLanguages();
        for (DbColumnInfo columnInfo : collection) {
            if(columnInfo.isVirtual()){
                continue;
            }
            // 使用过滤，且不包含，此处不考虑关联带出字段
            if (filter != null && !filter.getFieldsFilter().getFilterFields().contains(columnInfo.getColumnName())) {
                continue;
            }
            for (EcpLanguage language : currentEnableLanguages) {
                String columnName =
                        RepositoryUtil.FormatMuliLangColumnName(trans2DbColumnWithAlias(columnInfo.getColumnName()), language);
                String alias = RepositoryUtil.FormatMuliLangColumnName(columnInfo.getColumnName(), language);
                // 不使用过滤，则全部添加
                if (columns != null && columns.length() > 0) {
                    columns.append(",");
                }
                columns.append(columnName).append(" AS ").append(alias);
                if (!currentIndexMap.containsKey(alias)) {
                    currentIndexMap.put(alias, currentIndexMap.size());
                }
            }
        }
        return columns.toString();
    }

    // region Delete
    protected final String innerGetDeleteSql() {
        if (!getSqlSnippetCache().getInnerDeleteSqlMap().containsKey(entityDac.getGspDbtype().toString())) {
            String innerGetDeleteSql = getSqlSnippetProcessor().innerGetDeleteSql();
            getSqlSnippetCache().getInnerDeleteSqlMap().put(entityDac.getGspDbtype().toString(), innerGetDeleteSql);
            return innerGetDeleteSql;
        }
        return getSqlSnippetCache().getInnerDeleteSqlMap().get(entityDac.getGspDbtype().toString());
    }

    @Override
    public final int delete(String id, DataSaveParameter par) {
        if (getLogicDeleteInfo().isEnableLogicDelete()) {
            return logicDelete(id, par);
        }
        DataValidator.checkForEmptyString(id, "id");
        List<DbParameter> parameters = new ArrayList<>();
        parameters.add(buildParam("ID", GspDbDataType.VarChar, id));
        String sql = String
                .format("%1$s where %2$s.%3$s=?0", getDeleteSql(), getWrappedTableAlias(), getContainColumns().getPrimaryKey().getDbColumnName());

        List<FilterCondition> filter = par.getFilterCondition(getNodeCode(), id);
        if (filter != null && !filter.isEmpty()) {
            String condition = parseFilterCondition(getDB(), filter, parameters, parameters.size(),
                    false);
            sql = sql.concat(condition);
        }

        return executeSql(sql, parameters);

    }

    @Override
    public final String getDeleteSql() {
        String innerDelSql =  innerGetDeleteSql();
        if(CAFContext.current.getDbType() == DbType.MySQL){
            if(innerDelSql.indexOf("@TableName@") != innerDelSql.lastIndexOf("@TableName@")){//包含两个@TableName@
                innerDelSql = innerGetDeleteSql().replaceFirst("@TableName@", getWrappedTableAlias());
            }
        }
        return innerDelSql.replace("@TableName@", innerGetTableName());
    }

    public final int logicDelete(String id, DataSaveParameter par) {
        DataValidator.checkForEmptyString(id, "id");
        List<DbParameter> parameters = new ArrayList<>();
        parameters.add(buildParam(getLogicDeleteInfo().getLabelId(), GspDbDataType.Char, "1"));
        parameters.add(buildParam("ID", GspDbDataType.VarChar, id));
        String deleteSql = getModifySql() + " " + getLogicDeleteInfo().getLabelId() + " = ?0 where "
                + getContainColumns().getPrimaryKey().getDbColumnName() + "=?1 ";
        List<FilterCondition> filter = par.getFilterCondition(getNodeCode(), id);
        if (filter != null && !filter.isEmpty()) {
            String condition = parseFilterCondition(getDB(), filter, parameters, parameters.size(),
                    false);
            deleteSql = deleteSql.concat(condition);
        }

        return executeSql(deleteSql, parameters);
    }

    //delete from xxx
    protected final String getDeleteSqlBatch() {
        if (!getSqlSnippetCache().getDeleteSqlBatchMap().containsKey(entityDac.getGspDbtype().toString())) {
            String sql = getSqlSnippetProcessor().getDeleteSqlBatch();
            getSqlSnippetCache().getDeleteSqlBatchMap().put(entityDac.getGspDbtype().toString(), sql);
            return sql;
        }
        return getSqlSnippetCache().getDeleteSqlBatchMap().get(entityDac.getGspDbtype().toString());
    }

    @Override
    public final void delete(List<String> ids, DataSaveParameter par) {
        DataValidator.checkForNullReference(ids, "ids");
        if (ids.isEmpty()) {
            throw new IllegalArgumentException();
        }
        for (String item : ids) {
            FilterUtil.checkInParameterForSqlInjection(item);
        }
        String deleteSql = getModifySql() + " " + getLogicDeleteInfo().getLabelId() + " = ?0 where ";
        executeSql(formatFiscalAndMultiLang(getDeleteSqlBatch()) + getInFilter(ids), null);
    }

    // endregion

    public final void logicDelete(List<String> ids, DataSaveParameter par) {
        DataValidator.checkForNullReference(ids, "ids");
        if (ids.isEmpty()) {
            throw new IllegalArgumentException();
        }
        for (String item : ids) {
            FilterUtil.checkInParameterForSqlInjection(item);
        }
        executeSql(formatFiscalAndMultiLang(getDeleteSqlBatch()) + getInFilter(ids), null);
    }

    public final void deleteByParent(String joinInfo, String filter, List<DbParameter> dbPars) throws SQLException {
        if (CAFContext.current.getDbType() == DbType.MySQL) {
            String idWithAlias = String.format("%1$s.%2$s", getWrappedTableAlias(), getContainColumns().getPrimaryKey().getDbColumnName());
            if (getLogicDeleteInfo().isEnableLogicDelete()) {
                dbPars.add(buildParam(getLogicDeleteInfo().getLabelId(), GspDbDataType.Char, "1"));
                executeSql(String.format("update %1$s set %2$s = ?%8$s WHERE %3$s IN (SELECT t_id from(SELECT %4$s as t_id FROM %5$s %6$s WHERE %7$s) t )"
                        , getTableName(), getLogicDeleteInfo().getLabelId(), idWithAlias, idWithAlias, getTableName(), joinInfo, filter, dbPars.size() - 1), dbPars);
            } else {
                executeSql(String.format("%1$s WHERE %2$s IN (SELECT t_id from(SELECT %3$s as t_id FROM %4$s %5$s WHERE %6$s) t )"
                        , getDeleteSql(), idWithAlias, idWithAlias, getTableName(), joinInfo, filter), dbPars);
            }
        } else {
            String idWithAlias = String.format("%1$s.%2$s", getWrappedTableAlias(), getContainColumns().getPrimaryKey().getDbColumnName());
            if (getLogicDeleteInfo().isEnableLogicDelete()) {
                String primaryDbName = getContainColumns().getPrimaryKey().getDbColumnName();
                dbPars.add(buildParam(getLogicDeleteInfo().getLabelId(), GspDbDataType.Char, "1"));
                executeSql(String.format("update %1$s set %2$s = ?%8$s WHERE %3$s IN ( SELECT %4$s FROM %5$s %6$s WHERE %7$s )"
                        , innerGetTableName(), getLogicDeleteInfo().getLabelId(), primaryDbName, idWithAlias, getTableName(), joinInfo, filter, dbPars.size() - 1), dbPars);
            } else {
                executeSql(String.format("%1$s WHERE %2$s IN ( SELECT %3$s FROM %4$s %5$s WHERE %6$s )"
                        , getDeleteSql(), idWithAlias, idWithAlias, getTableName(), joinInfo, filter), dbPars);
            }
        }
    }

    // region Insert
    protected final String innerGetInsertSql() {
        if (!getSqlSnippetCache().getInnerInsertSqlMap().containsKey(entityDac.getGspDbtype().toString())) {
            String sql = getSqlSnippetProcessor().innerGetInsertSql();
            getSqlSnippetCache().getInnerInsertSqlMap().put(entityDac.getGspDbtype().toString(), sql);
            return sql;
        }
        return getSqlSnippetCache().getInnerInsertSqlMap().get(entityDac.getGspDbtype().toString());
    }

    protected String getInsertFields() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < adaptorItemList.size(); i++) {
            if (i > 0) {
                sb.append(",").append(adaptorItemList.get(i).getInsertFields(isMultiData));
            } else {
                sb.append(adaptorItemList.get(i).getInsertFields(isMultiData));
            }
        }
        return sb.toString();
        //region TODO 新增字段缓存起来
//        if (isMultiData) {
//            return getInsertFields_MultiLanguage(getContainColumns());
//        }
//        //TODO 后续加入生成基础be的插入字段
//        return getInsertFields(getContainColumns());
        //endregion
    }

    private String getInsertFields(DbColumnInfoCollection columns) {
        StringBuilder fields = new StringBuilder();
        boolean contain = false;
        for (DbColumnInfo containColumn : columns) {
            if (containColumn.getIsAssociateRefElement()) {
                continue;
            }
            if (contain)
                fields.append(",");
            String dbCol = containColumn.getDbColumnName();
            if (containColumn.getIsMultiLang()) {
                dbCol = dbCol + "@Language@";
            }
            fields.append(dbCol);
            contain = true;
        }
        return fields.toString();
    }

    private String getInsertFields_MultiLanguage(DbColumnInfoCollection columns) {
        StringBuilder fields = new StringBuilder();
        // 初始化
        insertMultiIndexMap = new HashMap<>();
        List<EcpLanguage> currentEnableLanguages = RepositoryUtil.getCurrentEnabledLanguages();
        for (DbColumnInfo containColumn : columns) {
            if (containColumn.getIsAssociateRefElement()) {
                continue;
            }
            // 多语单独处理
            if (containColumn.getIsMultiLang()) {
                for (EcpLanguage language : currentEnableLanguages) {
                    String alias = RepositoryUtil
                            .FormatMuliLangColumnName(containColumn.getColumnName(), language);
                    // 不使用过滤，则全部添加
                    if (fields.length() > 0) {
                        fields.append(",");
                    }
                    fields.append(alias);
                    if (insertMultiIndexMap.containsValue(alias)) {
                        throw new CefRepositoryException(alias + "列名重复");
                    }
                    insertMultiIndexMap.put(insertMultiIndexMap.size(), alias);
                }
                continue;
            }
            if (fields.length() > 0) {
                fields.append(",");
            }
            fields.append(containColumn.getDbColumnName());
            if (!insertMultiIndexMap.containsKey(containColumn.getDbColumnName())) {
                insertMultiIndexMap
                        .put(insertMultiIndexMap.size(), containColumn.getDbColumnName());
            }
        }
        return fields.toString();
    }

    protected String getInsertValues(RefObject<Integer> valuesCount) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < adaptorItemList.size(); i++) {
            if (i > 0) {
                sb.append(",").append(adaptorItemList.get(i).getInsertValues(isMultiData, valuesCount));
            } else {
                sb.append(adaptorItemList.get(i).getInsertValues(isMultiData, valuesCount));
            }
        }
        return sb.toString();
        //region TODO value缓存起来
//        if (isMultiData) {
//            return getInsertValues_MultiLanguage(getContainColumns(), valuesCount);
//        }
//        return getInsertValues(getContainColumns(),valuesCount);
        //ednregion
    }

    private String getInsertValues(DbColumnInfoCollection columns, RefObject<Integer> valuesCount) {
        StringBuilder values = new StringBuilder();
        for (DbColumnInfo containColumn : columns) {
            if (containColumn.getIsAssociateRefElement()) {
                continue;
            }
            if (valuesCount.argvalue > 0)
                values.append(",");
            values.append("?");
            valuesCount.argvalue = valuesCount.argvalue + 1;
        }
        return values.toString();
    }

    private String getInsertValues_MultiLanguage(DbColumnInfoCollection columns,
                                                 RefObject<Integer> valuesCount) {
        if (insertMultiIndexMap.isEmpty()) {
            throw new CefRepositoryException("包含多语信息的insertSql的列信息未组织");
        }
        StringBuilder values = new StringBuilder();
        for (Map.Entry<Integer, String> entrySet : insertMultiIndexMap.entrySet()) {
            if (valuesCount.argvalue > 0) {
                values.append(",");
            }
            values.append("?");
            valuesCount.argvalue = valuesCount.argvalue + 1;
        }
        return values.toString();
    }

    public final String getInsertSql() {
        return getInsertSql(new RefObject<Integer>(0));
    }

    private String getInsertSql(RefObject<Integer> fieldsCount) {
        return getInnerInsertSql(new RefObject<Integer>(0)).replace("@TableName@", innerGetTableName());
    }

    private String getInnerInsertSql(RefObject<Integer> fieldsCount) {
        Objects.requireNonNull(fieldsCount);

        String insertFields = getInsertFields();
        fieldsCount.argvalue = 0;
        String insertValues = getInsertValues(fieldsCount);

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder = stringBuilder.append("INSERT INTO @TableName@  (").append(insertFields);
        if (extendContainColumns != null && extendContainColumns.getCount() > 0)
            stringBuilder.append(",").append(getInsertFields(extendContainColumns));
        stringBuilder.append(" ) Values ( ").append(insertValues);
        if (extendContainColumns != null && extendContainColumns.getCount() > 0) {
            stringBuilder.append(getInsertValues(extendContainColumns, fieldsCount));
        }
        stringBuilder.append(")");
        return stringBuilder.toString();
    }

    @Override
    public int insert(IEntityData data, DataSaveParameter par, DacSaveContext bacher) throws SQLException {
        DataValidator.checkForNullReference(data, "data");
        List<FilterCondition> filter = par.getFilterCondition(getNodeCode(), data.getID());
        if (filter != null && !filter.isEmpty()) {
            throw new CefRepositoryException("新增不支持设置条件:" + data.getID());
        }

        isMultiData = (data instanceof IMultiLanguageData) && !((IMultiLanguageData) data)
                .getMultiLanguageInfos().isEmpty();

        String sql = getInsertSql(new RefObject<>(0));
        bacher.getJDBCExecutor().addBatch(formatFiscalAndMultiLang(sql, bacher), getInserParameters(data));
        return 1;
    }

    private List<DbParameter> getInserParameters(IEntityData data) {
        ArrayList<DbParameter> dbPars = new ArrayList<DbParameter>();
        if (isMultiData) {
            buildInsertParamters_MultiLanguage(data, dbPars);
        } else {
            buildInsertParamters(data, dbPars);
        }
        if (extendContainColumns != null && extendContainColumns.getCount() > 0)
            buildEXtendInsertParamters(data, dbPars);
        return dbPars;
    }

    private void buildInsertParamters_MultiLanguage(IEntityData entityData,
                                                    ArrayList<DbParameter> dbPars) {
        insertMultiIndexMap = getBaseAdaptorItem().getInsertMultiIndexMap();
        if (insertMultiIndexMap.isEmpty()) {
            throw new CefRepositoryException("包含多语信息的insertSql的列信息未组织");
        }
        IMultiLanguageData multiLanguageData =
                entityData instanceof IMultiLanguageData ? (IMultiLanguageData) entityData : null;
        for (Map.Entry<Integer, String> entry : insertMultiIndexMap.entrySet()) {
            String columnName = entry.getValue();
            // 多语
            if (getMultiLanguageAlias().containsKey(columnName)) {
                MultiLangColumnInfo multiLangColumnInfo = getMultiLanguageAlias().get(columnName);
                DbColumnInfo columnInfo = getContainColumns()
                        .getItem(multiLangColumnInfo.getColumnName());
                String language = multiLangColumnInfo.getLanguageInfo().getCode();
                String columnNameWithToken = multiLangColumnInfo.getColumnName()
                        + MultiLanguageInfo.MULTILANGUAGETOKEN;
                if (multiLanguageData != null && multiLanguageData.getMultiLanguageInfos()
                        .containsKey(columnNameWithToken)) {
                    Object value = multiLanguageData.getMultiLanguageInfos()
                            .get(columnNameWithToken)
                            .getPropValueMap().get(language);
                    if(columnInfo.getIsUdtElement())
                        value = getPropertyChangeValue(multiLangColumnInfo.getColumnName(), value);
                    dbPars.add(
                            buildParam(columnName, columnInfo.getColumnType(),
                                    value));
                    continue;
                }
                if (!language.equals(CAFContext.current.getLanguage())) {
                    dbPars.add(
                            buildParam(columnName, columnInfo.getColumnType(),
                                    null));
                    continue;
                }
                // 若为当前语言，需到data中对应属性中取数,走下面的普通分支
                columnName = multiLangColumnInfo.getColumnName();
            }
            // 普通
            Object value = this.getPersistenceValue(columnName, entityData);
            Object transValue =
                    value == null ? null : getPropertyChangeValue(columnName, value);
            DbColumnInfo columnInfo = getContainColumns().getItem(columnName);
            dbPars.add(
                    buildParam(columnInfo.getColumnName(), columnInfo.getColumnType(), transValue));
        }
    }

    private void buildEXtendInsertParamters(IEntityData entityData, ArrayList<DbParameter> dbPars) {
        for (DbColumnInfo columnInfo : extendContainColumns) {
            if (columnInfo.getIsAssociateRefElement()) {
                continue;
            }

            Object transValue = null;
            if (columnInfo.getIsUdtElement()) {
                for (AbstractDataAdapterExtendInfo info : getDataAdapterExtendInfos()) {
                    transValue = info.getUdtInsertValue(columnInfo.getColumnName(), columnInfo.getBelongElementLabel(), entityData);
                    if (transValue != null)
                        break;
                }
            } else {
                Object value = entityData.getValue(columnInfo.getColumnName());
                transValue = columnInfo.getTypeTransProcesser().transType(value);
            }

            dbPars.add(buildParam(columnInfo.getColumnName(), columnInfo.getColumnType(), transValue));
        }
    }

    //endregion
    // region modify
    protected final String innerGetModifySql() {
        if (!getSqlSnippetCache().getInnerModifySqlMap().containsKey(entityDac.getGspDbtype().toString())) {
            String sql = getSqlSnippetProcessor().innerGetModifySql();
            getSqlSnippetCache().getInnerModifySqlMap().put(entityDac.getGspDbtype().toString(), sql);
            return sql;
        }
        return getSqlSnippetCache().getInnerModifySqlMap().get(entityDac.getGspDbtype().toString());
    }

    private String getModifySql() {
        return innerGetModifySql().replace("@TableName@", innerGetTableName());
    }

    @Override
    public int modify(ModifyChangeDetail change, DataSaveParameter par, DacSaveContext ctx) throws SQLException {
        if ((change.getPropertyChanges() == null || change.getPropertyChanges().isEmpty()) && (
                change.getMultiLanguageInfos() == null || change.getMultiLanguageInfos().isEmpty())) {
            return 0;
        }
        List<DbParameter> parameters = new ArrayList<DbParameter>();
        RefObject<List<DbParameter>> parameters1 = new RefObject<List<DbParameter>>(parameters);
        String multiLanguageModifyValue = buildModifyValue_MultiLanguage(
                change.getMultiLanguageInfos(), parameters1);
        String modifyValue = buildModifyValue(change.getPropertyChanges(), parameters1, ctx);

        if (modifyValue.length() > 0) {
            if (multiLanguageModifyValue.length() > 0) {
                multiLanguageModifyValue = multiLanguageModifyValue.concat(", ");
            }
            multiLanguageModifyValue = multiLanguageModifyValue.concat(modifyValue);
        }
        parameters = parameters1.argvalue;
        if (multiLanguageModifyValue == null || multiLanguageModifyValue.length() == 0) {
            return 0;
        }
        int param = parameters.size();
        String execUpdateSql = getModifySql() + " " + multiLanguageModifyValue + " where "
                + getContainColumns().getPrimaryKey().getDbColumnName() + "=?" + (param);
        parameters.add(buildParam("ID", GspDbDataType.VarChar, change.getID().length(), change.getID()));

        List<FilterCondition> filter = par.getFilterCondition(getNodeCode(), change.getID());
        if (filter != null && !filter.isEmpty()) {
            String condition = parseFilterCondition(getDB(), filter, parameters, parameters.size(),
                    true);
            execUpdateSql = execUpdateSql.concat(condition);
        }

        execUpdateSql = formatFiscalAndMultiLang(execUpdateSql);
        return executeSql(execUpdateSql, parameters);
    }

    private String buildModifyValue(Map<String, Object> propertyChanges, RefObject<List<DbParameter>> parameters, DacSaveContext ctx) {
        StringBuilder modifyValue = new StringBuilder();
        int paramNum = parameters.argvalue.size();
        for (Map.Entry<String, Object> propertyChange : propertyChanges.entrySet()) {
            if (!(propertyChange.getValue() instanceof ValueObjModifyChangeDetail)) {
                DbColumnInfo dbColumnInfo = getContainColumns().getItem(propertyChange.getKey());
                if(dbColumnInfo == null || dbColumnInfo.isVirtual()){
                    continue;
                }

                String dbCol = trans2DbColumn(propertyChange.getKey());

                // 多语变更集中已经包含，则普通变更集不再包含
                if (parameters.argvalue.size() != 0) {
                    AtomicReference<Boolean> alreadyHas = new AtomicReference<>(false);
                    parameters.argvalue.forEach(para -> {
                        if (
                                para.getParamName()
                                        .equals(RepositoryUtil.FormatMuliLang(dbCol, ctx.getFieldSuffix()))) {
                            alreadyHas.set(true);
                            return;
                        }
                    });
                    if (alreadyHas.get()) {
                        continue;
                    }
                }

                if (modifyValue.length() > 0) {
                    modifyValue.append(" , ");
                }
                modifyValue.append(KeyWordsManager.getColumnAlias(dbCol) + " = ?" + (paramNum++));
                Object value = getContainColumns().getItem(propertyChange.getKey()).getTypeTransProcesser().transType(propertyChange.getValue());
                parameters.argvalue.add(buildParam(propertyChange.getKey(), getDataType(propertyChange.getKey()), getPropertyChangeValue(propertyChange.getKey(), value)));
            } else {
                paramNum = dealUdtModifyValue(propertyChange.getKey(), propertyChange.getValue(), paramNum, modifyValue, parameters.argvalue, null);
            }
        }

        for (AbstractDataAdapterExtendInfo info : getDataAdapterExtendInfos()) {
            info.buildModifyValues(modifyValue, propertyChanges, parameters);
        }
        return modifyValue.toString();
    }

    private int dealUdtModifyValue(String propertyName, Object propertyValue, int paramNum, StringBuilder modifyValue, List<DbParameter> parameters, String multiSuffix) {
        ArrayList<DbColumnInfo> columns = getUdtColumnInfos(propertyName);
        for (int i = 0; i < columns.size(); i++) {
            DbColumnInfo column = columns.get(i);
            if (column.getIsAssociateRefElement()) {
                continue;
            }
            String dbCol = column.getDbColumnName();
            if (column.getIsMultiLang()) {
                dbCol = dbCol + "@Language@";
            }
            if(multiSuffix != null && !"".equals(multiSuffix))
                dbCol = RepositoryUtil
                        .FormatMuliLangColumnName(dbCol, RepositoryUtil.getLanguage(multiSuffix));
            else if(column.getIsMultiLang()){
                // 多语变更集中已经包含，则普通变更集不再包含
                if (parameters.size() != 0) {
                    AtomicReference<Boolean> alreadyHas = new AtomicReference<>(false);
                    String finalDbCol = dbCol;
                    parameters.forEach(para -> {
                        if (
                                para.getParamName()
                                        .equals(RepositoryUtil.FormatMuliLang(finalDbCol))) {
                            alreadyHas.set(true);
                            return;
                        }
                    });
                    if (alreadyHas.get()) {
                        continue;
                    }
                }
            }

            if (i > 0) {
                modifyValue.append(" , ");
            }else if (columns.isEmpty() == false && paramNum > 0 && modifyValue.length() > 0) {
                modifyValue.append(" , ");
            }
            modifyValue.append(dbCol + " = ?" + (paramNum++));
            parameters.add(buildParam(dbCol, column.getColumnType(), getPropertyChangeValue(column.getColumnName(), propertyValue)));
        }

        return paramNum;
    }

    private String buildModifyValue_MultiLanguage(Map<String, MultiLanguageInfo> infos,
                                                  RefObject<List<DbParameter>> parameters) {
        if (parameters.argvalue == null) {
            parameters.argvalue = new ArrayList<DbParameter>();
        }
        StringBuilder modifyValue = new StringBuilder();
        int paramNum = parameters.argvalue.size();
        for (Map.Entry<String, MultiLanguageInfo> entrySet : infos.entrySet()) {
            String propName = entrySet.getKey().split(MultiLanguageInfo.MULTILANGUAGETOKEN)[0];

            for (Map.Entry<String, Object> item : entrySet.getValue().getPropValueMap()
                    .entrySet()) {
                String languageCode = item.getKey();
                Object value = item.getValue();
                if (!(value instanceof ValueObjModifyChangeDetail)) {
                    if (!getContainColumns().contains(propName)) {
                        continue;
                    }
                    DbColumnInfo columnInfo = getContainColumns().getItem(propName);

                    String dbCol = columnInfo.getRealColumnName();// trans2DbColumn(propName);
                    String columnName = RepositoryUtil
                            .FormatMuliLangColumnName(dbCol, RepositoryUtil.getLanguage(languageCode));

                    if (modifyValue.length() > 0) {
                        modifyValue.append(" , ");
                    }

                    modifyValue.append(columnName + " = ?" + (paramNum++));
                    parameters.argvalue.add(
                            buildParam(columnName, getDataType(propName), item.getValue())
                    );
                } else {
                    paramNum = dealUdtModifyValue(propName, value, paramNum, modifyValue, parameters.argvalue, languageCode);
                }

            }
        }
        return modifyValue.toString();
    }

    private ArrayList<DbColumnInfo> getUdtColumnInfos(String belongElementLabel) {
        ArrayList<DbColumnInfo> infos = new ArrayList<DbColumnInfo>();
        for (DbColumnInfo containColumn : getContainColumns()) {
            if (belongElementLabel.equals(containColumn.getBelongElementLabel())) {
                infos.add(containColumn);
            }
        }

        return infos;
    }

    protected  Object getPropertyChangeValue(String key, Object value)
    {
        DbColumnInfo dbColumnInfo=getContainColumns().getItem(key);
        if(dbColumnInfo.isUdtRefColumn())
        {
            if(value instanceof ValueObjModifyChangeDetail)
                value=((ValueObjModifyChangeDetail)value).getData();
            if(value instanceof ICefData ==false)
                return value;
//            return getNestedRepository(((UdtPropertyInfo)((ComplexUdtRefColumnInfo)dbColumnInfo).getBelongUdtPropertyInfo().getObjectInfo()).getUdtConfigId()).getPersistenceValue(((RefDataTypePropertyInfo) dbColumnInfo.getDataTypePropertyInfo()).getRefPropertyName(),
//                    (ICefData) data.getValue(((ComplexUdtRefColumnInfo)dbColumnInfo).getBelongUdtPropertyInfo().getPropertyName()));
            return getNestedRepository(((UdtPropertyInfo)((ComplexUdtRefColumnInfo)dbColumnInfo).getBelongUdtPropertyInfo().getObjectInfo()).getUdtConfigId()).getPersistenceValue(((RefDataTypePropertyInfo) dbColumnInfo.getDataTypePropertyInfo()).getRefPropertyName(),
                    (ICefData) value);
        }
        if(dbColumnInfo.getIsUdtElement())
        {
            if(value instanceof ValueObjModifyChangeDetail)
                value=((ValueObjModifyChangeDetail)value).getData();
            if(value instanceof ICefData ==false)
                return value;
            return getNestedRepository(((UdtPropertyInfo)dbColumnInfo.getDataTypePropertyInfo().getObjectInfo()).getUdtConfigId()).getPersistenceValue("",
                    (ICefData) value);
        }
        return dbColumnInfo.getPropertyChangeValue(value);
    }

    // endregion


    protected GspDbDataType getDataType(String key) {
        DbColumnInfo columnInfo = getColumnInfoByColumnNameName(key);
        if (columnInfo == null)
            throw new CefRepositoryException("找不到属性" + key + "对应的列信息");
        return columnInfo.getColumnType();

    }

    private DbColumnInfo getColumnInfoByColumnNameName(String columnName) {
        for (DbColumnInfo columnInfo : getContainColumns()) {
            if (columnInfo.getColumnName().toLowerCase().equals(columnName.toLowerCase()))
                return columnInfo;
        }
        for (AbstractDataAdapterExtendInfo extendInfo : getDataAdapterExtendInfos()) {
            DbColumnInfo columnInfo = extendInfo.tryGetColumnInfoByPropertyName(columnName);
            if (columnInfo != null)
                return columnInfo;
        }
        if (this.extendContainColumns != null && this.extendContainColumns.getCount() > 0) {
            for (DbColumnInfo columnInfo : this.extendContainColumns) {
                if (columnInfo.getColumnName().toLowerCase().equals(columnName.toLowerCase())) {
                    return columnInfo;
                }
            }
        }
        throw new CefRepositoryException("找不到属性" + columnName + "对应的列信息");
    }

    protected String trans2DbColumn(String key) {
        for (DbColumnInfo info : getContainColumns()) {
            if (info.getColumnName().equals(key)) {
                return info.getRealColumnName();
            }
        }
        throw new CefRepositoryException("未找到字段:" + key);
    }

    private DbColumnInfo getTempDbColumnInfo(String filedName) {
        DbColumnInfo columnInfo = null;
        columnInfo = getContainColumns().getItem(filedName);
        if (columnInfo == null) {
            if (!isInitColumn) {
                columnInfo = tempContainColumns.getItem(filedName);
            }
            if (columnInfo == null)
                columnInfo = extendContainColumns.getItem(filedName);
        } else {
            if (columnInfo.getIsAssociateRefElement() && !isInitColumn) {
                columnInfo = tempContainColumns.getItem(filedName);
            }
        }
        return columnInfo;
    }

    private String trans2DbColumnWithAlias(String filedName) {
        return trans2DbColumnWithAlias(filedName, false);
    }

    /**
     * 带别名的字段格式  表别名.数据库字段名
     * @param filedName   字段名
     * @param ignoreAlias  是否忽略大小写
     * @return
     */
    protected final String trans2DbColumnWithAlias(String filedName, boolean ignoreAlias) {
        filedName=DatabaseUtil.getColumnName(filedName);
        if (!(getContainColumns().contains(filedName) || tempContainColumns.contains(filedName)) && (extendContainColumns == null || !extendContainColumns.contains(filedName))) {

            StringBuilder sb = new StringBuilder();
            sb.append("当前BE[v2]:" + getWrappedTableAlias() + " configId:" + getConfigId() + " 忽略大小写:" + ignoreAlias);
            sb.append("\r\n");
            sb.append("包含列信息{{");
            for (DbColumnInfo dbColumnInfo : getContainColumns()) {
                sb.append(dbColumnInfo.getColumnName() + ",");
            }
            sb.append("}}");
            logger.error("未找到字段" + filedName + "，请确认字段名称是否输入正确，或关联引用字段是否已经获取");
            logger.error(sb.toString());
            //再换种方式比较一次？
            for (DbColumnInfo columnInfo : getContainColumns()) {
                if (columnInfo.getColumnName().toLowerCase().equals(filedName.toLowerCase())) {
                    logger.error("找到字段" + filedName + "");
                }
            }
            throw new CefRepositoryException("未找到字段" + filedName + "，请确认字段名称是否输入正确，或关联引用字段是否已经获取");
        }
        DbColumnInfo columnInfo = null;
        columnInfo = getContainColumns().getItem(filedName);
        if (columnInfo == null) {
            if (!isInitColumn) {
                columnInfo = tempContainColumns.getItem(filedName);
            }
            if (columnInfo == null)
                columnInfo = extendContainColumns.getItem(filedName);
        } else {
            if (columnInfo.getIsAssociateRefElement() && !isInitColumn) {
                columnInfo = tempContainColumns.getItem(filedName);
            }
        }
        if (columnInfo.getIsAssociateRefElement()) {
            if (ignoreAlias) {
                throw new CefRepositoryException("当前持久化操作不支持使用带出字段" + columnInfo.getColumnName());
            } else {
                return getAssociateDbColumnName(columnInfo);
            }
        }
        //return assColumns.ContainsKey(filedName) ? assColumns[filedName] : throw new Exception("Error");

        String dbName = ignoreAlias ? columnInfo.getDbColumnName()
                : getWrappedTableAlias() + "." + columnInfo.getDbColumnName();
        if (columnInfo.getIsMultiLang()) {
            dbName = dbName + "@Language@";
        }
        return dbName;
    }

    private String getAssociateDbColumnName(DbColumnInfo columnInfo) {
        if (columnInfo.getDbColumnName() == null || columnInfo.getDbColumnName().length() == 0) {
            throw new CefRepositoryException("尚未获取关联引用字段数据库列名称，请先获取引用字段");
        }
        return columnInfo.getDbColumnName();
    }

    protected final String getGetDataByIdsSql() {
        if (!getSqlSnippetCache().getGetDataByIdsSqlMap().containsKey(entityDac.getGspDbtype().toString())) {
            String sql = getSqlSnippetProcessor().getGetDataByIdsSql();
            getSqlSnippetCache().getGetDataByIdsSqlMap().put(entityDac.getGspDbtype().toString(), sql);
            return sql;
        }
        return getSqlSnippetCache().getGetDataByIdsSqlMap().get(entityDac.getGspDbtype().toString());
    }


    @Override
    public List<IEntityData> getDataByIds(List<String> dataIds, EntityFilter nodeFilter, RetrieveFilter retrieveFilter) {
        initQueryTableName();
        for (String item : dataIds) {
            FilterUtil.checkInParameterForSqlInjection(item);
        }
        String tableName = getQueryTableNameWithAuthority(null, nodeFilter);
        String fields = getQueryFields(nodeFilter);
        String sql = String.format(getGetDataByIdsSql(), fields, tableName, "%1$s");

        return getDatasBatch(formatFiscalAndMultiLang(sql, retrieveFilter), dataIds);
    }

    protected final String getGetDataByIdSql() {
        if (!getSqlSnippetCache().getGetDataByIdSqlMap().containsKey(entityDac.getGspDbtype().toString())) {
            String sql = getSqlSnippetProcessor().getGetDataByIdSql();
            getSqlSnippetCache().getGetDataByIdSqlMap().put(entityDac.getGspDbtype().toString(), sql);
            return sql;
        }
        return getSqlSnippetCache().getGetDataByIdSqlMap().get(entityDac.getGspDbtype().toString());
    }

    @Override
    public IEntityData getDataByID(String dataId) {
        return getDataByID(dataId, null);
    }

    public IEntityData getDataByID(String dataId, EntityFilter filter) {
        RetrieveFilter rtFilter = new RetrieveFilter();
        rtFilter.getNodeFilters().put(getNodeCode(), filter);
        return this.getDataByIDWithPara(dataId, new AdaptorRetrieveParam(rtFilter));
    }


    public IEntityData getDataByIDWithPara(String dataId, AdaptorRetrieveParam adaptorRetrieveParam) {
        EntityFilter filter = adaptorRetrieveParam.getEntityfilter(getNodeCode());
        if (filter != null && filter.getFieldsFilter() != null && filter.getFieldsFilter().getFilterFields() != null) {
            if (getVersionControlPropName() != null && getVersionControlPropName().equals("") == false &&
                    filter.getFieldsFilter().getFilterFields().contains(getVersionControlPropName()) == false)
                filter.getFieldsFilter().getFilterFields().add(getVersionControlPropName());
            if (getPrimaryKey() != null && getPrimaryKey().equals("") == false && filter.getFieldsFilter().getFilterFields().contains(getPrimaryKey()))
                filter.getFieldsFilter().getFilterFields().add(getPrimaryKey());
        }

        initQueryTableName();
        String tableName = getQueryTableNameWithAuthority(null, adaptorRetrieveParam != null ? adaptorRetrieveParam.getEntityfilter(getNodeCode()) : null);
        String fields = getQueryFields(adaptorRetrieveParam);
        String sql = String.format(getGetDataByIdSql(), fields, tableName, "?0 ");

        try {
            List<DbParameter> list = new ArrayList<DbParameter>();
            list.add(buildParam("ID", GspDbDataType.VarChar, dataId));
            if (getLogicDeleteInfo().isEnableLogicDelete()) {
                sql += String.format(" and %1$s =?1 ", getWrappedTableAlias() + "." + getLogicDeleteInfo().getLabelId());
                list.add(buildParam(getLogicDeleteInfo().getLabelId(), GspDbDataType.Char, "0"));
            }
            RetrieveFilter retrieveFilter = adaptorRetrieveParam == null ? null : adaptorRetrieveParam.getRetrieveFilter();
            return innerGetData(formatMultiLang(sql, retrieveFilter), list, adaptorRetrieveParam);
        } catch (RuntimeException ex) {
            throw  new CefRepositoryException(buildMessage(ex.getMessage()),ex);
        }
    }

    protected  AdaptorSqlCache getAdaptorSqlCache()
    {
        return getSqlSnippetCache().getAdaptorSqlCache();
    }

    protected  SqlSnippetCache getSqlSnippetCache()
    {return (SqlSnippetCache) entityResInfo.getSqlSnippetCache();}

    public  boolean getIsChild(){return false;}

    private AdapterUQChecker getAdapterUQChecker() {
        return new AdapterUQChecker(this);
    }


    private IEntityData innerGetData(String sql, List<DbParameter> parameters, AdaptorRetrieveParam param) {
        ArrayList<IEntityData> datas = getDatas(sql, parameters, param);
        return datas.stream().findFirst().orElse(null);
    }

    public final String getParentJoin() {
        if (!getSqlSnippetCache().getParentJoinMap().containsKey(entityDac.getGspDbtype().toString())) {
            String sql = getSqlSnippetProcessor().parentJoin();
            getSqlSnippetCache().getParentJoinMap().put(entityDac.getGspDbtype().toString(), sql);
            return sql;
        }
        return getSqlSnippetCache().getParentJoinMap().get(entityDac.getGspDbtype().toString());
    }


    protected boolean getHasMultiLangCol() {
        if (hasMultiLangCol == null) {
            for (DbColumnInfo col : getContainColumns()) {
                if (col.getIsMultiLang()) {
                    hasMultiLangCol = true;
                    break;
                }
            }
            return hasMultiLangCol;
        }
        return false;
    }

    private Query buildQueryManager(String sqlText, List<DbParameter> parameters) {
        Query query = getDbProcessor().buildQueryManager(entityManager, sqlText, parameters);
        return query;
    }

    @Transactional
    protected int executeSql(String sqlText, List<DbParameter> parameters) {

        Query query = buildQueryManager(sqlText, parameters);
        return query.executeUpdate();

    }

    protected Object executeScelar(String sqlText, List<DbParameter> parameters) {
        DataValidator.checkForEmptyString(sqlText, "sqlText");

        Query query = buildQueryManager(sqlText, parameters);
        List<Object[]> resultSet = query.getResultList();
        return resultSet.get(0)[0];
    }


    //private String FormatFiscal(String sql)
    //{
    //    return RepositoryUtil.FormatFiscal(sql, Convert.ToString(DboID));
    //}

    private String formatMultiLang(String sql) {
        return RepositoryUtil.FormatMuliLang(sql);
    }

    private String getUniquenessSQL(UQConstraintMediate mediate, ArrayList<DbParameter> parameters) {
        if (mediate.getParametersInfo().isEmpty()) {
            return null;
        }
        int index = 0;
        StringBuilder sql = new StringBuilder();
        sql.append(String.format("SELECT COUNT(1) FROM %1$s ", innerGetTableName()));
        RefObject<Integer> tempRef_index = new RefObject<Integer>(index);
        sql.append(String.format(" WHERE %1$s", getUQSql(mediate, tempRef_index, parameters)));
        index = tempRef_index.argvalue;
        return sql.toString();
    }

    private String getUQSql(UQConstraintMediate mediate, RefObject<Integer> index, ArrayList<DbParameter> parameters) {
        StringBuilder sql = new StringBuilder();

        HashMap<String, HashMap<String, Object>> info = mediate.getParametersInfo();
        ArrayList<String> exceptIDs = new ArrayList<String>();
        exceptIDs.addAll(mediate.getExceptDeleteIds());
        exceptIDs.addAll(mediate.getExceptModifyIds());

        StringBuilder id = new StringBuilder();
        for (String item : exceptIDs) {
            id.append("'" + item + "'" + ",");
        }

        StringBuilder or = new StringBuilder();
        int count1 = info.keySet().size() - 1;
        int j = 0;
        for (String item : info.keySet()) {
            or.append("(");
            HashMap<String, Object> fieldsInfo = info.get(item);
            int count2 = fieldsInfo.keySet().size() - 1;
            int i = 0;
            for (Map.Entry<String, Object> field : fieldsInfo.entrySet()) {
                String column = trans2DbColumn(field.getKey());
                Object value = null;
                if (false)
//				if (field.getValue() instanceof IUdtData)
                {
                    value = field.getValue();
                } else {
                    value = getContainColumns().getItem(field.getKey()).getTypeTransProcesser().transType(field.getValue());
                }
                try {
                    Object dbValue = getPropertyChangeValue(field.getKey(), value);
                    parameters.add(buildParam(field.getKey() + "_" + (new Integer(j)).toString(), getDataType(field.getKey()), dbValue));

                    if (dbValue == null) {
                        or.append(String.format("%1$s=? or %1$s is null", column));
                    } else {
                        or.append(String.format("%1$s=?", column));
//						or.append($" {column}={" {" + index++ + "}"} ");
                    }

                    //or.Append(column + "=" + "'" + value + "' ");
                    if (i != count2) {
                        or.append(" AND ");
                    }
                    i++;
                } catch (Exception e) {
                    throw e;
                }

            }
            or.append(")");
            if (j != count1) {
                or.append(" OR ");
            }
            j++;
        }
        if (id.length() != 0) {
            sql.append(String.format("(%1$s) AND ID NOT IN (%2$s)", or.toString(), id.toString().substring(0, id.toString().length() - 1)));
        } else {
            sql.append(String.format("(%1$s)", or.toString()));
        }


        return sql.toString();
    }


    protected final String getJoinTableName() {
        if (!getSqlSnippetCache().getJoinTableNameMap().containsKey(entityDac.getGspDbtype().toString())) {
            String sql = getSqlSnippetProcessor().getJoinTableName();
            getSqlSnippetCache().getJoinTableNameMap().put(entityDac.getGspDbtype().toString(), sql);
            return sql;
        }
        return getSqlSnippetCache().getJoinTableNameMap().get(entityDac.getGspDbtype().toString());
    }

    @Override
    public String getTableNameByColumns(HashMap<String, String> columns, String keyColumnName, RefObject<String> keyDbColumnName, ArrayList<String> tableAlias) {
        //跟之前一致。
        ArrayList<String> keys1 = new ArrayList<>();
        for (String key : columns.keySet()
        ) {
            keys1.add(key);
        }
        ArrayList<AssociationInfo> associations = getAssociationInfos(keys1);
        String tableName = getTableNamesWithAssociationInfo(associations, tableAlias);
        keyDbColumnName.argvalue = trans2DbColumnWithAlias(keyColumnName);

        String[] keys = keys1.toArray(new String[]{});
        for (int i = 0; i < keys.length; i++) {
            columns.put(keys[i], trans2DbColumnWithAlias(keys[i]));
        }
        return tableName;
    }

    /**
     * 要求关联字段的拼接，在这里进行 把带出字段放在后面。。
     * @param columns
     * @param keyColumnName
     * @param keyDbColumnName
     * @param tableAlias
     * @return
     */
    @Override
    public String getTableNameByRefColumns(HashMap<String, RefColumnInfo> columns, String keyColumnName, RefObject<String> keyDbColumnName, ArrayList<String> tableAlias) {
        //跟之前一致。
        isInitColumn = false;
        ArrayList<AssociationInfo> associations = getAssociationInfos(columns);
        String tableName = getTableNamesWithAssociationInfo(associations, tableAlias);
        keyDbColumnName.argvalue = trans2DbColumnWithAlias(keyColumnName);

        List<String> keys = new ArrayList<String>();
        for (String key : columns.keySet()) {
            keys.add(key);
        }
        for (int i = 0; i < keys.size(); i++) {
            if(isColumnExists(keys.get(i))){
                RefColumnInfo tempVar = new RefColumnInfo();
                tempVar.setColumnName(trans2DbColumnWithAlias(keys.get(i)));
                DbColumnInfo tempDbColumnInfo = getTempDbColumnInfo(keys.get(i));
                tempVar.setTransProcesser(tempDbColumnInfo.getTypeTransProcesser());
                tempVar.setColumnType(tempDbColumnInfo.getColumnType());
                tempVar.setVirtual(tempDbColumnInfo.isVirtual());
                tempVar.setFieldReposExtendConfigClassImpl(tempDbColumnInfo.getFieldReposExtendConfigClassImpl());
                tempVar.setFieldReposExtendConfigId(tempDbColumnInfo.getFieldReposExtendConfigId());
                columns.put(keys.get(i), tempVar);
            }
            else{
                columns.remove(keys.get(i));
            }
        }
        return tableName;
    }

    public String getTableNameByRefColumns(TableNameRefContext tableNameRefContext) {
        if(!StringUtils.isNullOrEmpty(tableNameRefContext.getRefTableAlias())){
            setTableAlias(tableNameRefContext.getRefTableAlias());
        }
        isInitColumn = false;
        ArrayList<AssociationInfo> associations = getAssociationInfos(tableNameRefContext.getColumns());
        String tableName = getTableNamesWithAssociationInfo(associations, tableNameRefContext.getTableAlias());
        tableNameRefContext.getKeyDbColumnName().argvalue = trans2DbColumnWithAlias(tableNameRefContext.getKeyColumnName());

        List<String> keys = new ArrayList<String>();
        for (String key : tableNameRefContext.getColumns().keySet()) {
            keys.add(key);
        }
        for (int i = 0; i < keys.size(); i++) {
            if(isColumnExists(keys.get(i))){
                RefColumnInfo tempVar = new RefColumnInfo();
                tempVar.setColumnName(trans2DbColumnWithAlias(keys.get(i)));
                DbColumnInfo tempDbColumnInfo = getTempDbColumnInfo(keys.get(i));
                tempVar.setTransProcesser(tempDbColumnInfo.getTypeTransProcesser());
                tempVar.setColumnType(tempDbColumnInfo.getColumnType());
                tempVar.setVirtual(tempDbColumnInfo.isVirtual());

                tempVar.setFieldReposExtendConfigClassImpl(tempDbColumnInfo.getFieldReposExtendConfigClassImpl());
                tempVar.setFieldReposExtendConfigId(tempDbColumnInfo.getFieldReposExtendConfigId());
                tableNameRefContext.getColumns().put(keys.get(i), tempVar);
            }
            else{
                tableNameRefContext.getColumns().remove(keys.get(i));
            }
        }
        return tableName;
    }

    /**
     * 给定的列名在当前节点是否存在
     * 兼容部分场景查询报错的问题
     * @param filedName
     * @return
     */
    private boolean isColumnExists(String filedName){
        if (!(getContainColumns().contains(filedName) || tempContainColumns.contains(filedName)) && (extendContainColumns == null || !extendContainColumns.contains(filedName))) {
            return false;
        }
        return true;
    }

    private ArrayList<AssociationInfo> getAssociationInfos(HashMap<String, RefColumnInfo> columnInfos) {
        ArrayList<String> columns = new ArrayList<String>();
        for (String item : columnInfos.keySet()) {
            columns.add(item);
        }
        ArrayList<AssociationInfo> associations = new ArrayList<AssociationInfo>();
        for (String columnItem : columns) {
            //如果是关联带出字段 或者 当前不包含
            if (isRefOrUdt(columnItem)) {
                AssociationInfo assoInfo = findInAssociationInfos(columnItem);
                //是否多值多列udt,多值单列的不会进来。
                if (assoInfo == null&&getEntityResInfo()!=null) {
                    //如果是多值多列udt
                    DataTypePropertyInfo dataTypePropertyInfo = getEntityResInfo().getEntityTypeInfo().getPropertyInfos().get(columnItem);
                    Object udtPropertyInfo = null;
                    if(dataTypePropertyInfo != null){
                        udtPropertyInfo = dataTypePropertyInfo.getObjectInfo();
                    }
                    if (udtPropertyInfo != null && udtPropertyInfo instanceof ComplexUdtPropertyInfo) {
                        if (columnInfos.containsKey(columnItem)) {
                            columnInfos.remove(columnItem);
                        }
                        for (Map.Entry<String, DataTypePropertyInfo> entry : ((ComplexUdtPropertyInfo) udtPropertyInfo).getPropertyInfos().entrySet()) {
                            if (!columnInfos.containsKey(entry.getKey())) {
                                columnInfos.put(entry.getKey(), new RefColumnInfo());
                            }
                        }
                    } else {
                        //详细输出一下错误信息：  是否统计一下，错误次数达到一定次数，进行回复？ 重置columns信息
                        StringBuilder sbError = new StringBuilder();
                        sbError.append("当前节点[getAssociationInfos]:" + getTableAlias() + " configId:" + getConfigId());
                        sbError.append("未找到字段:" + columnItem);
                        sbError.append("\r\n");
                        sbError.append("包含字段信息{{");
                        for (DbColumnInfo dbColumnInfo : getContainColumns()) {
                            sbError.append(dbColumnInfo.getColumnName() + ",");
                        }
                        sbError.append("}}");
                        logger.error(sbError.toString());
                        throw new CefRepositoryException("找不到字段：" + columnItem);
                    }
                } else {
                    if (!associations.contains(assoInfo)) {
                        associations.add(assoInfo);
                    }
                }
            }

            //如果是关联字段
            if (isAssociationElement(columnItem)) {
                AssociationInfo assoInfo = getAssociation(columnItem);
                if (!associations.contains(assoInfo)) {
                    associations.add(assoInfo);
                    for (String refColumn : assoInfo.getRefColumns().keySet()) {
                        if (!columnInfos.containsKey(refColumn)) {
                            columnInfos.put(refColumn, new RefColumnInfo());
                        }
                    }
                }
            }
        }
        return associations;
    }

    /**
     * 如果是关联带出字段或者Udt字段
     * @param columnItem
     * @return
     */
    private boolean isRefOrUdt(String columnItem){
        //基础字段/扩展字段都不包含
        DbColumnInfo column = getContainColumns().getItem(columnItem);
        if(column != null && column.getIsAssociateRefElement()){
            return true;
        }
        DbColumnInfo extendColumn = this.extendContainColumns.getItem(columnItem);
        if(extendColumn != null && extendColumn.getIsAssociateRefElement()){
            return true;
        }
        if((column == null) && (extendColumn == null)){
            return true;
        }
        return false;
    }

    /**
     * 是否关联字段
     * @param columnItem
     * @return
     */
    private boolean isAssociationElement(String columnItem){
        if(getContainColumns().contains(columnItem) && getContainColumns().getItem(columnItem).getIsAssociation()){
            return true;
        }
        if(this.extendContainColumns != null && this.extendContainColumns.contains(columnItem) && this.extendContainColumns.getItem(columnItem).getIsAssociation()){
            return true;
        }
        return false;
    }

    private ArrayList<AssociationInfo> getAssociationInfos(ArrayList<String> columns) {
        ArrayList<AssociationInfo> associations = new ArrayList<AssociationInfo>();
        for (String columnItem : columns) {
            if (!getContainColumns().contains(columnItem) || getContainColumns().getItem(columnItem).getIsAssociateRefElement()) {
                AssociationInfo assoInfo = findInAssociationInfos(columnItem);
                if (associations.contains(assoInfo)) {
                    associations.add(assoInfo);
                }
            }

            if (getContainColumns().contains(columnItem) && getContainColumns().getItem(columnItem).getIsAssociation()) {
                AssociationInfo assoInfo = getAssociation(columnItem);
                if (associations.contains(assoInfo)) {
                    associations.add(assoInfo);
                }
            }
        }
        return associations;
    }

    private AssociationInfo findInAssociationInfos(String columnName) {
        for (AssociationInfo associationInfo : getAssociationInfos()) {
            if (associationInfo.getRefColumns().containsKey(columnName)) {
                return associationInfo;
            }
        }
        return null;
//        throw new RuntimeException("找不到字段" + columnName);
    }


    private String getTableNamesWithAssociationInfo(ArrayList<AssociationInfo> associations, ArrayList<String> tableAlias) {
        //
        if (tableAlias == null || tableAlias.size() == 0) {
            tableAlias = new ArrayList<String>();
            addTableAlias(tableAlias);
        } else {
            if(StringUtils.isNullOrEmpty(this.originTableAlias)){
                this.originTableAlias = getTableAlias();
            }
            setTableAlias(getTableAlias4Association(tableAlias));
        }
        if (associations == null || associations.size() < 1) {
            return getTableName();
        }

        return buildTableNamesWithAssociationInfo(associations, tableAlias, getTableName());
    }

    private String buildTableNamesWithAssociationInfo(ArrayList<AssociationInfo> associations, ArrayList<String> tableAlias, String baseTableName) {
        StringBuilder queryTables = new StringBuilder();
        StringBuilder fullTable = new StringBuilder().append(baseTableName);
        for (AssociationInfo associationInfo : associations) {
            if(associationInfo==null)
                continue;
            HashMap<String, RefColumnInfo> associationColumns = new HashMap<String, RefColumnInfo>();
            if(associationInfo!=null) {
                for (Map.Entry<String, String> item :
                        associationInfo.getRefColumns().entrySet()) {
                    associationColumns.put(item.getValue(), new RefColumnInfo());
                }
            }

            if (getConfigId().equals(associationInfo.getConfigId()) && getNodeCode() == associationInfo.getNodeCode()) {
                queryTables.append(getCurrentAssoTableName(associationInfo, tableAlias, associationColumns));
                continue;
            }
            String targetDbColumnName = "";
            associationInfo.getRefRepository().initParams(getPars());
            RefObject<String> tempRef_targetDbColumnName = new RefObject<String>(targetDbColumnName);
            String tableName = "";
            try{
                tableName = associationInfo.getRefRepository().getTableNameByRefColumns(associationInfo.getNodeCode(), associationColumns, associationInfo.getTargetColumn(), tempRef_targetDbColumnName, tableAlias);
            }
            catch (Exception ex){
                StringBuilder sbError = new StringBuilder();
                if(associationInfo != null){
                    sbError.append("当前BE: "+getTableAlias()+" 关联BE:" + associationInfo.getRefRepository().getClass().getName());
                    sbError.append("关联节点:["+associationInfo.getNodeCode()+"]" + " sourceColumn:" + associationInfo.getSourceColumn() + " targetColumn:" + associationInfo.getTargetColumn());
                    sbError.append("\r\n带出字段：");
                    if(associationColumns != null && associationColumns.size() > 0){
                        for (String item : associationColumns.keySet()) {
                            sbError.append(item + ",");
                        }
                    }
                    logger.error(sbError.toString());
                }
                throw new CefRepositoryException("根据关联条件获取表名报错", ex);
            }
            targetDbColumnName = tempRef_targetDbColumnName.argvalue;

            if (isInitColumn) {
                initAssociateColumnInfo(associationInfo, associationColumns);
            } else {
                initTempAssociateColumnInfo(associationInfo, associationColumns);
            }
            if(this.fieldsFilter != null && this.fieldsFilter.isUseFieldsCondition()){
                if (!this.fieldsFilter.getFilterFields().contains(associationInfo.getSourceColumn())) {
                    continue;
                }
            }
            String[] tables = tableName.split(" LEFT OUTER JOIN ", 2);

            String sourceColumnName = trans2DbColumnWithAlias(associationInfo.getSourceColumn());
            queryTables.append(String.format(getJoinTableName(), tables[0], sourceColumnName, targetDbColumnName));
            buildAssoCondi(queryTables, associationInfo, targetDbColumnName, tables[0]);
            if(tables.length > 1){
                queryTables.append(" LEFT OUTER JOIN "+tables[1]);
            }
        }
        joinTableName = queryTables.toString();
        fullTable.append(joinTableName);
        return fullTable.toString();
    }

    private void buildAssoCondi(StringBuilder queryTables, AssociationInfo associationInfo, String targetDbColumnName, String tableName){
        //todo 这个地方别名处理待验证,字段如果与数据库不一致？ 前端直接用数据库的？
        if(associationInfo.getAssoConditions() != null && associationInfo.getAssoConditions().size() >0){
            String targetAlias = targetDbColumnName.substring(0, targetDbColumnName.indexOf("."));
            for(AssoCondition assoCondition: associationInfo.getAssoConditions()){
                if(StringUtils.isEmpty(assoCondition.getValue())){
                    queryTables.append(" and " + getAssoAlias(assoCondition.getLeftNodeCode(), tableName) + "." + assoCondition.getLeftField());
                    queryTables.append(StringUtils.isEmpty(assoCondition.getOperator()) ? "=" : assoCondition.getOperator());
                    queryTables.append(getAssoAlias(assoCondition.getRightNodeCode(), targetAlias) + "." + assoCondition.getRightField());
                }
                else {
                    queryTables.append(" and " + getAssoAlias(assoCondition.getLeftNodeCode(), targetAlias) + "." + assoCondition.getLeftField());
                    queryTables.append(StringUtils.isEmpty(assoCondition.getOperator()) ? "=" : assoCondition.getOperator());
                    //todo wangmj 先按照字符串处理，后续结合类型处理
                    queryTables.append(" '" + assoCondition.getValue()+"' " );
                }
            }
        }
    }
    private String getAssoAlias(String nodeCode, String targetTableName){
        if(getTableAlias().equals(nodeCode))
            return getTableAlias();
        return targetTableName;
    }
    private String getCurrentAssoTableName(AssociationInfo associationInfo, ArrayList<String> tableAlias, HashMap<String, RefColumnInfo> associationColumns) {
        String currnetAlias = getTableAlias4Association(tableAlias);
        ArrayList<AssociationInfo> associations = getAssociationInfos(associationColumns);
        String tableName = buildTableNamesWithAssociationInfo(associations, tableAlias, innerGetTableName() + " " + currnetAlias);
        String keyDbColumnName = currnetAlias + "." + trans2DbColumn(associationInfo.getTargetColumn());

        ArrayList<String> keys = new ArrayList<String>();
        for (String key :
                associationColumns.keySet()) {
            keys.add(key);
        }
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            RefColumnInfo tempVar = new RefColumnInfo();
            tempVar.setColumnName(currnetAlias + "." + trans2DbColumn(key));
            tempVar.setTransProcesser(getContainColumns().getItem(key).getTypeTransProcesser());
            tempVar.setColumnType(getContainColumns().getItem(key).getColumnType());
            associationColumns.put(key, tempVar);
        }

        if (isInitColumn) {
            initAssociateColumnInfo(associationInfo, associationColumns);
        } else {
            initTempAssociateColumnInfo(associationInfo, associationColumns);
        }

        String sourceColumnName = trans2DbColumnWithAlias(associationInfo.getSourceColumn());
        return String.format(getJoinTableName(), tableName, sourceColumnName, keyDbColumnName);

    }

    private void addTableAlias(ArrayList<String> tableAlias) {
        tableAlias.add(getWrappedTableAlias());
    }

    private String getTableAlias4Association(ArrayList<String> tableAlias) {
        if (!tableAlias.contains(getWrappedTableAlias())) {
            tableAlias.add(getWrappedTableAlias());
            return getWrappedTableAlias();
        }

        int index = 1;
        while (true) {
            if (tableAlias.contains(getWrappedTableAlias(true) + index)) {
                index++;
            } else {
                tableAlias.add(getWrappedTableAlias(true) + index);
                return getWrappedTableAlias(true) + index;
            }
        }
    }

    private void initAssociateColumnInfo(AssociationInfo associationInfo, HashMap<String, RefColumnInfo> associationColumns) {
        if (!AssoMapping.containsKey(associationInfo.getSourceColumn())) {
            AssoMapping.put(associationInfo.getSourceColumn(), new HashMap<String, String>());
        }

        for (Map.Entry<String, String> refColumnItem : associationInfo.getRefColumns().entrySet()) {
            if (!AssoMapping.get(associationInfo.getSourceColumn()).containsKey(refColumnItem.getValue())) {
                AssoMapping.get(associationInfo.getSourceColumn()).put(refColumnItem.getValue(), refColumnItem.getKey());
            }
            //这个地方也得加上 扩展字段集合？
            if (getBaseAdaptorItem().getContainColumns().contains(refColumnItem.getKey())) {
                DbColumnInfo columnInfo = getContainColumns().getItem(refColumnItem.getKey());
                RefColumnInfo refColumnInfo = associationColumns.get(refColumnItem.getValue());
                columnInfo.setDbColumnName(refColumnInfo.getColumnName());
                ITypeTransProcesser tempVar = refColumnInfo.getTransProcesser();
                columnInfo.setTypeTransProcesser((ITypeTransProcesser) ((tempVar instanceof ITypeTransProcesser) ? tempVar : null));
                columnInfo.setColumnType(refColumnInfo.getColumnType());
                columnInfo.setVirtual(refColumnInfo.isVirtual());
                columnInfo.setFieldReposExtendConfigClassImpl(refColumnInfo.getFieldReposExtendConfigClassImpl());
                columnInfo.setFieldReposExtendConfigId(refColumnInfo.getFieldReposExtendConfigId());
                associationColumns.remove(refColumnItem.getValue());
            } else {
                //TODO：改成抛异常
                if (!associationColumns.containsKey(refColumnItem.getValue())) {
                    continue;
                }

                DbColumnInfo refColumnInfo =  ((EntityRelationalAdaptor)(((BaseRootRepository)associationInfo.getRefRepository()).getEntityDac(associationInfo.getNodeCode()).getEntityAdaptor())).getContainColumns().getItem(refColumnItem.getValue());
                RefColumnInfo refAssocColumnInfo = associationColumns.get(refColumnItem.getValue());
                ITypeTransProcesser tempVar2 = refAssocColumnInfo.getTransProcesser();
                DbColumnInfo tempVar3 = new DbColumnInfo();
                tempVar3.setColumnName(refColumnItem.getKey());
                tempVar3.setDbColumnName(refAssocColumnInfo.getColumnName());
                tempVar3.setVirtual(refAssocColumnInfo.isVirtual());
                tempVar3.setFieldReposExtendConfigClassImpl(refAssocColumnInfo.getFieldReposExtendConfigClassImpl());
                tempVar3.setFieldReposExtendConfigId(refAssocColumnInfo.getFieldReposExtendConfigId());
                if(refColumnInfo==null) {
                    tempVar3.setTypeTransProcesser((ITypeTransProcesser) ((tempVar2 instanceof ITypeTransProcesser) ? tempVar2 : null));
                    tempVar3.setColumnType(refAssocColumnInfo.getColumnType());
                }
                else {
                    tempVar3.setTypeTransProcesser(refColumnInfo.getTypeTransProcesser());
                    tempVar3.setColumnType(refColumnInfo.getColumnType());
                }
                tempVar3.setIsAssociateRefElement(true);
                tempVar3.setBelongElementLabel(associationInfo.getSourceColumn());
                DbColumnInfo columnInfo = tempVar3;
                boolean containedInExtendAssoc = false;
                if (this.extendAssociations != null && this.extendAssociations.size() > 0) {
                    for (AssociationInfo ass : this.extendAssociations) {
                        if (ass.getTargetColumn().equals(associationInfo.getTargetColumn()) && ass.getSourceColumn().equals(associationInfo.getSourceColumn())) {
                            this.extendContainColumns.add(columnInfo);
                            containedInExtendAssoc = true;
                            break;
                        }
                    }
                }
                if (!containedInExtendAssoc) {
                    getBaseAdaptorItem().addColumn(columnInfo);
                }
                associationColumns.remove(refColumnItem.getValue());
            }

        }

        for (Map.Entry<String, RefColumnInfo> associationColumn : associationColumns.entrySet()) {
            DbColumnInfo tempVar4 = new DbColumnInfo();
            tempVar4.setColumnName(associationInfo.getSourceColumn() + "_" + associationColumn.getKey());
            tempVar4.setDbColumnName(associationColumn.getValue().getColumnName());
            tempVar4.setFieldReposExtendConfigClassImpl(associationColumn.getValue().getFieldReposExtendConfigClassImpl());
            tempVar4.setFieldReposExtendConfigId(associationColumn.getValue().getFieldReposExtendConfigId());
            tempVar4.setTypeTransProcesser((ITypeTransProcesser) ((associationColumn.getValue().getTransProcesser() instanceof ITypeTransProcesser) ? associationColumn.getValue().getTransProcesser() : null));
            tempVar4.setColumnType(associationColumn.getValue().getColumnType());
            tempVar4.setIsAssociateRefElement(true);
            tempVar4.setBelongElementLabel(associationInfo.getSourceColumn());

            DbColumnInfo columnInfo = tempVar4;
            getBaseAdaptorItem().getContainColumns().add(columnInfo);
            if (!AssoMapping.get(associationInfo.getSourceColumn()).containsKey(associationColumn.getKey())) {
                AssoMapping.get(associationInfo.getSourceColumn()).put(associationColumn.getKey(), associationInfo.getSourceColumn() + "_" + associationColumn.getKey());
            }
        }
    }

    public DbColumnInfoCollection getAllContainColumns() {
        if (this.extendContainColumns != null && this.extendContainColumns.getCount() > 0) {
            DbColumnInfoCollection col = new DbColumnInfoCollection();
            col.addRange(getContainColumns());
            col.addRange(this.extendContainColumns);
            return col;
        }
        return getContainColumns();
    }

    private void initTempAssociateColumnInfo(AssociationInfo associationInfo, HashMap<String, RefColumnInfo> associationColumns) {
        if (!AssoMapping.containsKey(associationInfo.getSourceColumn())) {
            AssoMapping.put(associationInfo.getSourceColumn(), new HashMap<String, String>());
        }

        for (Map.Entry<String, String> refColumnItem : associationInfo.getRefColumns().entrySet()) {
            if (!AssoMapping.get(associationInfo.getSourceColumn()).containsKey(refColumnItem.getValue())) {
                AssoMapping.get(associationInfo.getSourceColumn()).put(refColumnItem.getValue(), refColumnItem.getKey());
            }
            if (tempContainColumns.contains(refColumnItem.getKey())) {
                DbColumnInfo columnInfo = tempContainColumns.getItem(refColumnItem.getKey());
                RefColumnInfo refColumnInfo = associationColumns.get(refColumnItem.getValue());
                columnInfo.setDbColumnName(refColumnInfo.getColumnName());

                ITypeTransProcesser tempVar = refColumnInfo.getTransProcesser();
                columnInfo.setTypeTransProcesser((ITypeTransProcesser) ((tempVar instanceof ITypeTransProcesser) ? tempVar : null));
                columnInfo.setColumnType(refColumnInfo.getColumnType());
                columnInfo.setVirtual(refColumnInfo.isVirtual());
                columnInfo.setFieldReposExtendConfigClassImpl(refColumnInfo.getFieldReposExtendConfigClassImpl());
                columnInfo.setFieldReposExtendConfigId(refColumnInfo.getFieldReposExtendConfigId());
                associationColumns.remove(refColumnItem.getValue());
            } else {
                //TODO：改成抛异常
                if (!associationColumns.containsKey(refColumnItem.getValue())) {
                    continue;
                }
                RefColumnInfo refColumnInfo = associationColumns.get(refColumnItem.getValue());
                ITypeTransProcesser tempVar2 = refColumnInfo.getTransProcesser();
                DbColumnInfo tempVar3 = new DbColumnInfo();
                tempVar3.setColumnName(refColumnItem.getKey());
                tempVar3.setDbColumnName(refColumnInfo.getColumnName());
                tempVar3.setTypeTransProcesser((ITypeTransProcesser) ((tempVar2 instanceof ITypeTransProcesser) ? tempVar2 : null));
                tempVar3.setColumnType(refColumnInfo.getColumnType());
                tempVar3.setIsAssociateRefElement(true);
                tempVar3.setBelongElementLabel(associationInfo.getSourceColumn());
                tempVar3.setVirtual(refColumnInfo.isVirtual());
                tempVar3.setFieldReposExtendConfigClassImpl(refColumnInfo.getFieldReposExtendConfigClassImpl());
                tempVar3.setFieldReposExtendConfigId(refColumnInfo.getFieldReposExtendConfigId());
                DbColumnInfo columnInfo = tempVar3;
                boolean containedInExtendAssoc = false;
                if (this.extendAssociations != null && this.extendAssociations.size() > 0) {
                    for (AssociationInfo ass : this.extendAssociations) {
                        if (ass.getTargetColumn().equals(associationInfo.getTargetColumn()) && ass.getSourceColumn().equals(associationInfo.getSourceColumn())) {
                            this.extendContainColumns.add(columnInfo);
                            containedInExtendAssoc = true;
                            break;
                        }
                    }
                }
                if (!containedInExtendAssoc) {
                    tempContainColumns.add(columnInfo);
                }
                associationColumns.remove(refColumnItem.getValue());
            }
        }

        for (Map.Entry<String, RefColumnInfo> associationColumn : associationColumns.entrySet()) {
            DbColumnInfo tempVar4 = new DbColumnInfo();
            tempVar4.setColumnName(associationInfo.getSourceColumn() + "_" + associationColumn.getKey());
            tempVar4.setDbColumnName(associationColumn.getValue().getColumnName());
            tempVar4.setTypeTransProcesser((ITypeTransProcesser) ((associationColumn.getValue().getTransProcesser() instanceof ITypeTransProcesser) ? associationColumn.getValue().getTransProcesser() : null));
            tempVar4.setColumnType(associationColumn.getValue().getColumnType());
            tempVar4.setIsAssociateRefElement(true);
            tempVar4.setBelongElementLabel(associationInfo.getSourceColumn());
            tempVar4.setVirtual(associationColumn.getValue().isVirtual());
            tempVar4.setFieldReposExtendConfigClassImpl(associationColumn.getValue().getFieldReposExtendConfigClassImpl());
            tempVar4.setFieldReposExtendConfigId(associationColumn.getValue().getFieldReposExtendConfigId());
            DbColumnInfo columnInfo = tempVar4;
            tempContainColumns.add(columnInfo);
            if (!AssoMapping.get(associationInfo.getSourceColumn()).containsKey(associationColumn.getKey())) {
                AssoMapping.get(associationInfo.getSourceColumn()).put(associationColumn.getKey(), associationInfo.getSourceColumn() + "_" + associationColumn.getKey());
            }
        }
    }

    private ArrayList<String> getMissingDataIds(String sqlInString, ArrayList<String> dataIds) {
        String sql = "Select " + getPrimaryKey() + " from " + innerGetTableName() + " where " + getPrimaryKey() + " in (" + sqlInString + ")";
        List<DbParameter> dbPars = null;
        if (getLogicDeleteInfo().isEnableLogicDelete()) {
            sql += " and " + getLogicDeleteInfo().getLabelId() + " =?0";
            dbPars = new ArrayList<>();
            dbPars.add(buildParam(getLogicDeleteInfo().getLabelId(), GspDbDataType.Char, "0"));
        }
        ArrayList<String> dbDataIds = getDataIds(sql, dbPars);
        ArrayList<String> missingDataIds = new ArrayList<String>();

        for (String item : dataIds) {
            if (dbDataIds.contains(item) == false) {
                missingDataIds.add(item);
            }
        }
        return missingDataIds;
    }

    private ArrayList<String> getDataIds(String sql, List<DbParameter> parameters) {

        Query query = buildQueryManager(sql, parameters);
        List<Object[]> result = query.getResultList();
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 0; i < result.size(); i++) {
            if (result.get(i) instanceof Object[]) {
                list.add(String.valueOf(result.get(i)[0]));
            } else {
                list.add(String.valueOf(result.get(i)));
            }
        }
        return list;
    }

    private String getSqlInString(ArrayList<String> dataIds) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < dataIds.size(); i++) {
            String item = dataIds.get(i);
            sb.append(String.format("'%1$s'", item));
            if (i != dataIds.size() - 1) {
                sb.append(",");
            }
        }
        return sb.toString();
    }

    @Override
    public Object readProperty(String propertyName, ICefReader reader) {
        return ((BaseAdaptorItem)getBaseAdaptorItem()).readProperty(propertyName,reader);
    }

    @Override
    public Object getPersistenceValue(String colName, ICefData data) {
        DbColumnInfo dbColumnInfo=getContainColumns().getItem(colName);
        if(dbColumnInfo.isUdtRefColumn())
        {
            return getNestedRepository(((UdtPropertyInfo)((ComplexUdtRefColumnInfo)dbColumnInfo).getBelongUdtPropertyInfo().getObjectInfo()).getUdtConfigId()).getPersistenceValue(((RefDataTypePropertyInfo) dbColumnInfo.getDataTypePropertyInfo()).getRefPropertyName(),
                    (ICefData) data.getValue(((ComplexUdtRefColumnInfo)dbColumnInfo).getBelongUdtPropertyInfo().getPropertyName()));
        }
        if(dbColumnInfo.getIsUdtElement())
        {
            return getNestedRepository(((UdtPropertyInfo)dbColumnInfo.getDataTypePropertyInfo().getObjectInfo()).getUdtConfigId()).getPersistenceValue("",
                    (ICefData) data.getValue(dbColumnInfo.getDataTypePropertyInfo().getPropertyName()));
        }
        return dbColumnInfo.getPersistenceValue(data.getValue(dbColumnInfo.getDataTypePropertyInfo().getPropertyName()));
    }


    public CefEntityResInfoImpl getEntityResInfo() {
        return entityResInfo;
    }
}
